package com.yanqu.road.server.manager.activity.tonbing.activity;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.camp.CampUnion;
import com.yanqu.road.entity.activity.tonbing.CrossTonBingRankSort;
import com.yanqu.road.entity.activity.tonbing.config.TonBingCampBoxConfig;
import com.yanqu.road.entity.activity.tonbing.config.TonBingCityConfig;
import com.yanqu.road.entity.activity.tonbing.config.TonBingTitleConfig;
import com.yanqu.road.entity.activity.tonbing.data.*;
import com.yanqu.road.entity.activity.tonbing.join.CrossTonBingUnionJoin;
import com.yanqu.road.entity.activity.tonbing.join.CrossTonBingUnionJoinMember;
import com.yanqu.road.entity.activity.tongbing.data.CrossTongBingUserData;
import com.yanqu.road.entity.activity.tongbing.join.CrossTongBingUnionJoin;
import com.yanqu.road.entity.activity.tongbing.join.CrossTongBingUnionJoinMember;
import com.yanqu.road.entity.enums.activity.tonbing.eTonBingPosition;
import com.yanqu.road.entity.enums.activity.tonbing.eTonBingRedDotType;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.eMessageType;
import com.yanqu.road.entity.enums.eSceneType;
import com.yanqu.road.entity.enums.eUnionPosition;
import com.yanqu.road.entity.log.cross.fivehero.LogFiveHeroPatronsUpdate;
import com.yanqu.road.entity.log.cross.tongbing.peak.LogTonBingAppoint;
import com.yanqu.road.entity.log.cross.tongbing.peak.LogTonBingJoin;
import com.yanqu.road.entity.log.cross.tongbing.peak.LogTonBingLockUnion;
import com.yanqu.road.entity.log.cross.tongbing.peak.LogTonBingUnionPeak;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.scene.UserScene;
import com.yanqu.road.entity.union.UnionBaseInfo;
import com.yanqu.road.logic.bussiness.activity.TonBingActivityBusiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.helper.UnionActivityGroupHelper;
import com.yanqu.road.logic.pb.CrossTonBingPb;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.logic.pb.UnionBasePb;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.pb.activity.TonBingProto;
import com.yanqu.road.pb.commonactivity.CommonActivityProto;
import com.yanqu.road.pb.cross.activity.CrossActivityProto;
import com.yanqu.road.pb.rank.RankProto;
import com.yanqu.road.pb.worldmessage.WorldMessageProto;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.activity.ActivityMgr;
import com.yanqu.road.server.manager.activity.camp.Camp;
import com.yanqu.road.server.manager.activity.camp.CampApi;
import com.yanqu.road.server.manager.activity.camp.eCampActivityType;
import com.yanqu.road.server.manager.activity.tonbing.logic.CrossTonBingChatLogic;
import com.yanqu.road.server.manager.activity.tonbing.task.BaseCrossTonBingActivityTask;
import com.yanqu.road.server.manager.activity.tonbing.task.impl.CrossTonBingLockUnionTask;
import com.yanqu.road.server.manager.activity.tonbing.task.impl.CrossTonBingMakeMatchTask;
import com.yanqu.road.server.manager.activity.tonbing.task.impl.CrossTonBingSetWinnerTask;
import com.yanqu.road.server.manager.log.CrossAutoLogMgr;
import com.yanqu.road.server.manager.scene.CrossSceneMgr;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.protocol.*;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

public class CrossTonBingActivity extends CrossTonBingBaseAc implements CampApi {

    private RandomHelper randomHelper = new RandomHelper();

    private AtomicInteger matchId = new AtomicInteger(1);

    /**
     * 活动总数据
     */
    private CrossTonBingDataMain crossTonBingDataMain;

    /**
     * 轮次,战场，比赛id
     */
    private Map<Integer,Map<Integer,Map<Integer,CrossTonBingMatch>>> turnMatchMap = new ConcurrentHashMap<>();

    //缓存所有玩家的所在场次信息
    private Map<Long,CrossTonBingMatch> userMatchMap = new ConcurrentHashMap<>();

    //matchId
    private Map<Integer,CrossTonBingMatch> matchMap = new ConcurrentHashMap<>();


    /**
     * 商会数据
     */
    private Map<String, CrossTonBingUnionJoin> unionJoinMap = new ConcurrentHashMap<>();

    /**
     * 玩家数据
     */
    private Map<Long, CrossTonBingUserData> userDataMap = new ConcurrentHashMap<>();

    /**
     * 阵营数据
     */
    private Map<Integer, CrossTonBingCampData> campDataMap = new ConcurrentHashMap<>();

    //userId matchId
    private Map<Long,Integer> watchMap = new ConcurrentHashMap<>();



    //获得每个阵营第一名的战功玩家
    public Map<Integer,Long> getCampMaxZhanGongUnionUserIdMap() {
        Map<Integer,Long> campIdUserIdMap = new ConcurrentHashMap<>();
        for(int campId : campUserRankMap.keySet()){
            long userId = 0;
            CrossTonBingRankListModel rankListModel = campUnionRankMap.get(campId);
            if (rankListModel != null) {
                LinkedList<CrossTonBingRank> rankList = rankListModel.getRankList();
                if (!rankList.isEmpty()) {
                    CrossTonBingRank first = rankList.getFirst();
                    CrossTonBingUnionJoin join = getUnionJoin(first.getId());
                    if(join != null){
                        for(CrossTonBingUnionJoinMember member : join.getMemberMap().values()){
                            if(member.getPosition() == eUnionPosition.Master.getValue()){
                                userId = member.getUserId();
                                break;
                            }
                        }
                    }
                }
            }
            campIdUserIdMap.put(campId,userId);
            if(userId != 0){
                CrossTonBingUserData userData = getUserData(userId);
                Map<Integer, Integer> posMap = userData.getPositionMap();
                posMap.put(userData.getCampId(),eTonBingPosition.Master.getValue());
                Map<Integer,Integer> appointMap = new ConcurrentHashMap<>();
                appointMap.put(userData.getCampId(),eTonBingPosition.Master.getValue());
                userData.setPositionMap(posMap);
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
                if (userBaseInfo != null) {
                    TonBingProto.CrossTonBingCityWinerAppointRespMsg.Builder crespMsg = TonBingProto.CrossTonBingCityWinerAppointRespMsg.newBuilder();
                    crespMsg.setWinerName("");
                    parsePosAppoint(crespMsg,appointMap);
                    crespMsg.setCampId(userData.getCampId());
                    crespMsg.setSendReward(true);
                    MessageHelper.sendPacket(userBaseInfo.getServerId(), userId, YanQuMessageUtils.buildMessage(GameProtocol.S_CROSS_TON_BING_CITY_APPOINT_POSITION, crespMsg));
                }
            }
        }
        return campIdUserIdMap;
    }

    /**
     * 设置城主
     */
    public void crossTonBingSetWinnerTask() {
        // 已经设置城主
        if (crossTonBingDataMain.getWinnerMap().size() != 0L) {
            return;
        }
        // 时间未到
        long nowTime = System.currentTimeMillis();
        if (nowTime < config.getActivityInfo().getEndTime() * 1000L) {
            addTask(new CrossTonBingSetWinnerTask(this, config.getActivityInfo().getEndTime() * 1000L));
            return;
        }
        // 时间过了
        if (nowTime > config.getActivityInfo().getEndShowTime() * 1000L) {
            return;
        }
        int lastTurn = config.getLastTurn();
        int lastWarType = config.getLastWayType();
        //没找到这一轮
        if(!turnMatchMap.containsKey(lastTurn)){
            return;
        }
        //没找到这个战场
        if(!turnMatchMap.get(lastTurn).containsKey(lastWarType)){
            return;
        }
        Map<Integer,CrossTonBingMatch> matchMap = turnMatchMap.get(lastTurn).get(lastWarType);
        //原则上只能有一个分组，多了就不玩了
        if(matchMap.size() != 1){
            return;
        }
        for(CrossTonBingMatch match : matchMap.values()){
            // 正常设置
            Map<Integer, TonBingCityConfig> cityConfigMap = config.getCityConfigMap(match.getCrossTonBingData().getWarType());
            for (TonBingCityConfig cityConfig : cityConfigMap.values()) {
                if (cityConfig.getType() == 6) {
                    Map<Integer, CrossTonBingCity> cityMap = match.getCrossTonBingData().getCityMap();
                    CrossTonBingCity cityData = cityMap.get(cityConfig.getId());
                    int campId = cityData.getCampId();
                    long winnerUserId = 0L;
                    if (campId == 0) {
                        // 没有城主
                        logger.error("ton bing activityId {} no winner!", config.getActivityInfo().getActivityId());
                        winnerUserId = getMaxZhanGongUserId();
                    } else {
                        winnerUserId = match.getCampMaxZhanGongUserId(campId);
                    }
                    Map<Integer,Long> campIdUserIdMap = match.getCampMaxZhanGongUnionUserIdMap();
                    campIdUserIdMap.put(0,winnerUserId);
                    crossTonBingDataMain.setWinnerMap(campIdUserIdMap);
                    if(winnerUserId != 0){
                        CrossTonBingUserData userData = getUserData(winnerUserId);
                        Map<Integer, Integer> posMap = userData.getPositionMap();
                        //可能任命多个，只发一个的奖励
                        Map<Integer, Integer> appointMap = new ConcurrentHashMap<>();
                        posMap.put(0,eTonBingPosition.Master.getValue());
                        appointMap.put(0,eTonBingPosition.Master.getValue());
                        userData.setPositionMap(posMap);
                        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(winnerUserId);
                        if (userBaseInfo != null) {
                            TonBingProto.CrossTonBingCityWinerAppointRespMsg.Builder crespMsg = TonBingProto.CrossTonBingCityWinerAppointRespMsg.newBuilder();
                            crespMsg.setWinerName("");
                            parsePosAppoint(crespMsg,appointMap);
                            crespMsg.setCampId(userData.getCampId());
                            crespMsg.setSendReward(true);
                            //別一启动就来这里，会发送失败
                            MessageHelper.sendPacket(userBaseInfo.getServerId(), winnerUserId, YanQuMessageUtils.buildMessage(GameProtocol.S_CROSS_TON_BING_CITY_APPOINT_POSITION, crespMsg));
                        }
                    }
                    syncWinnerGetNotice();
                    Map<Integer,Long> winnerMap = crossTonBingDataMain.getWinnerMap();
                    for(long userId : winnerMap.values()){
                        addRedDot(getUserData(userId),eTonBingRedDotType.Type12_BeAppoint);
                        addRedDot(getUserData(userId),eTonBingRedDotType.Type11_Appoint);
                    }
                    return;
                }
            }
        }
        Map<Integer,Long> winnerMap = crossTonBingDataMain.getWinnerMap();
        for(long userId : winnerMap.values()){
            addRedDot(getUserData(userId),eTonBingRedDotType.Type12_BeAppoint);
            addRedDot(getUserData(userId),eTonBingRedDotType.Type11_Appoint);
        }
    }


    //城池有了同步客户端告诉他要出图标了
    public void syncWinnerGetNotice() {
        for (long serverId : config.getActivityInfo().getServerIdList()) {
            TonBingProto.CrossTonBingReqMsg.Builder reqMsg = TonBingProto.CrossTonBingReqMsg.newBuilder();
            reqMsg.setActivityId(config.getActivityInfo().getActivityId());
            MessageHelper.sendPacket(serverId, 0, YanQuMessageUtils.buildMessage(GameProtocol.S_TON_BING_SYNC_USER_DATA, reqMsg));
        }
    }
    // ============================== 缓存数据 ==============================

    // 聊天
    private CrossTonBingChatLogic chatLogic;

    // 榜单
    private CrossTonBingRankListModel userRank = new CrossTonBingRankListModel(); // 个人榜
    private Map<Integer, CrossTonBingRankListModel> campUserRankMap = new ConcurrentHashMap(); // 阵营内个人榜
    private Map<Integer, CrossTonBingRankListModel> campUnionRankMap = new ConcurrentHashMap<>(); // 阵营内商会榜

    // 城主职位
    private Map<Long, List<CrossTonBingUserData>> needSyncPosUserData = new ConcurrentHashMap<>();

    // ============================== 构造方法 ==============================

    public CrossTonBingActivity(ActivityInfo activityInfo) {
        super(activityInfo);
        int nowTurn = config.getTurn();
        // 【读取数据】

        crossTonBingDataMain = TonBingActivityBusiness.getCrossTonBingDataMain(activityInfo.getActivityId());
        if (crossTonBingDataMain == null) {
            crossTonBingDataMain = new CrossTonBingDataMain();
            crossTonBingDataMain.setActivityId(activityInfo.getActivityId());
            crossTonBingDataMain.setLockUnion(false);
            crossTonBingDataMain.setInsertOption();
        }
        userDataMap = TonBingActivityBusiness.getCrossTonBingUserDataMap(activityInfo.getActivityId());
        campDataMap = TonBingActivityBusiness.getCrossTonBingCampDataMap(activityInfo.getActivityId());
        unionJoinMap = TonBingActivityBusiness.getCrossTonBingUnionJoinMap(activityInfo.getActivityId());
        matchId = new AtomicInteger(TonBingActivityBusiness.getMaxMatchId(activityInfo.getActivityId()));

        //↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑本类↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
        Map<Integer,List<CrossTonBingCityWarReport>> cityWarReportMap =
                TonBingActivityBusiness.getCityReportListMap(activityInfo.getActivityId());
        Map<Integer,List<CrossTonBingUserWarReport>> userWarReportsMap =
                TonBingActivityBusiness.getUserReportListMap(activityInfo.getActivityId());
        Map<Integer,Map<Integer, CrossTonBingCampMatchData>> campMatchDataMap =
                TonBingActivityBusiness.getCrossTonBingCampMatchDataMap(activityInfo.getActivityId());

        Map<Integer,CrossTonBingData> crossTonBingDataMap = TonBingActivityBusiness.getCrossTonBingDataMap(activityInfo.getActivityId());
        for(CrossTonBingData crossTonBingData : crossTonBingDataMap.values()){
            CrossTonBingMatch match = new CrossTonBingMatch(config,crossTonBingData);
            List<CrossTonBingCityWarReport> cityWarReportList = cityWarReportMap.getOrDefault(crossTonBingData.getMatchId(),new ArrayList<>());
            List<CrossTonBingUserWarReport> userWarReportsList = userWarReportsMap.getOrDefault(crossTonBingData.getMatchId(),new ArrayList<>());
            Map<Integer, CrossTonBingCampMatchData> campDataMap = campMatchDataMap.getOrDefault(crossTonBingData.getMatchId(),new ConcurrentHashMap<>());
            Map<String, CrossTonBingUnionJoin> joinMap = new ConcurrentHashMap<>();
            Map<Long, CrossTonBingUserData> userDataMap = new ConcurrentHashMap<>();
            for(String unionId : crossTonBingData.getUnionIdList()){
                joinMap.put(unionId,unionJoinMap.get(unionId));
                for(long userId : unionJoinMap.get(unionId).getMemberMap().keySet()){
                    userDataMap.put(userId,getUserData(userId));
                }
            }
            match.initData(cityWarReportList,userWarReportsList,campDataMap,joinMap,userDataMap);
            match.initAllRankList();
            if(!turnMatchMap.containsKey(crossTonBingData.getTurn())){
                turnMatchMap.put(crossTonBingData.getTurn(),new ConcurrentHashMap<>());
            }
            if(!turnMatchMap.get(crossTonBingData.getTurn()).containsKey(crossTonBingData.getWarType())){
                turnMatchMap.get(crossTonBingData.getTurn()).put(crossTonBingData.getWarType(),new ConcurrentHashMap<>());
            }
            turnMatchMap.get(crossTonBingData.getTurn()).get(crossTonBingData.getWarType()).put(crossTonBingData.getMatchId(),match);
            matchMap.put(crossTonBingData.getMatchId(),match);
            if(crossTonBingData.getTurn() == nowTurn){
                //玩家有资格就会一直比赛，每一轮都有他，当前的轮次才是现在的比赛
                for(long userId : userDataMap.keySet()){
                    userMatchMap.put(userId,match);
                }
                match.start();
            }
        }




        // 【其他初始化】
        initUserRedPacketNumMap(); // 初始化红包发送数量
        initNeedSyncPositionUser();
        chatLogic = new CrossTonBingChatLogic(activityInfo);
        initAllRankList();

        // 启动线程
        initTask();
        thread.start();
    }


    // ============================== 数据生成获取 ==============================

    /**
     * 初始化需要同步的会获得银两的职位的玩家
     */
    private void initNeedSyncPositionUser() {
        Map<Integer,Map<Integer, TonBingTitleConfig>> titleConfigMap = config.getTitleConfigMap();
        for (CrossTonBingUserData userData : userDataMap.values()) {
            Map<Integer,Integer> posMap = userData.getPositionMap();
            if (posMap.size() != 0) {
                addNeedSyncPosUser(userData);
            }
        }
    }

    //触发玩家被任命后的增益银两收成，这里只用定时器去触发，就不加锁了
    //需求是城主加成英两且获得别人扣除的英两，通过领取，增益buff的也是加银两然后领取，减益buff的玩家要去本服他的英两收益变小
    public void makePosSliver() {
        //原先只用来扣银两，现在没有扣银两的职位了

        //领奖期才能任命
        long nowTime = System.currentTimeMillis();
        if (nowTime < config.getActivityInfo().getEndTime() * 1000 || nowTime > config.getActivityInfo().getEndShowTime() * 1000) {
            return;
        }
        Map<Integer, Map<Integer, TonBingTitleConfig>> titleConfigMap = config.getTitleConfigMap();
        for (CrossTonBingUserData userData : userDataMap.values()) {
            synchronized (lock) {
                Map<Integer, Integer> posMap = userData.getPositionMap();
                for(int posType : posMap.keySet()){
                    if (posMap.get(posType) != eTonBingPosition.None.getValue()) {
                        TonBingTitleConfig titleConfig = titleConfigMap.get(posType).get(posMap.get(posType));
                        if (titleConfig.getType() == 1) {
                        /*long lastCalTime = userData.getPosAddSilverTime();
                        long sec = (nowTime - lastCalTime) / 1000;
                        Map<Long, BigInteger> addMap = userData.getPosAddSilverMap();
                        BigInteger earnSpeed = getUserEarnSpeed(userData.getUserId());
                        BigInteger oldValue = addMap.getOrDefault(userData.getUserId(), BigInteger.ZERO);
                        BigInteger addValue = BigInteger.valueOf(sec).multiply(earnSpeed).multiply(BigInteger.valueOf(titleConfig.getEffect())).divide(BigInteger.valueOf(1000));
                        addMap.put(userData.getUserId(), oldValue.add(addValue));
                        userData.setPosAddSilverMap(addMap);
                        userData.setPosAddSilverTime(nowTime);*/
                        } else if (titleConfig.getType() == 2) {
                            long lastCalTime = userData.getPosAddSilverTime();
                            long sec = (nowTime - lastCalTime) / 1000;
                            BigInteger earnSpeed = getUserEarnSpeed(userData.getUserId());
                            BigInteger addValue = BigInteger.valueOf(sec).multiply(earnSpeed).multiply(BigInteger.valueOf(titleConfig.getEffect())).divide(BigInteger.valueOf(1000));
                            // 累计上缴银两
                            userData.setTotalPosSilver(userData.getTotalPosSilver().add(addValue));
                            //每个人分配到的不一样
                            posSliverAdd(addValue,userData.getUserId());
                            userData.setPosAddSilverTime(nowTime);
                        }
                    }
                }
            }
        }
        syncUserPositionSliver();
    }

    public void calcAllBarracks() {
        for(CrossTonBingMatch match : matchMap.values()){
            if(!match.isGameOver()){
                match.calcAllBarracks();
            }
        }
    }


    //按照配在百分百算钱
    private void posSliverAdd(BigInteger addValue,long userId) {
        Map<Integer,Map<Integer, TonBingTitleConfig>> titleConfigMap = config.getTitleConfigMap();
        Map<Integer,Integer> allAddWeightMap = new ConcurrentHashMap<>();
        for (Integer campId : titleConfigMap.keySet()) {
            int allAddWeight = 0;
            for (TonBingTitleConfig titleConfig : titleConfigMap.get(campId).values()) {
                if (titleConfig.getType() == 1) {
                    allAddWeight = allAddWeight + titleConfig.getEffect();
                }
            }
            allAddWeightMap.put(campId,allAddWeight);
        }

        for (CrossTonBingUserData userData : userDataMap.values()) {
            Map<Integer, Integer> posMap = userData.getPositionMap();
            for(int posType : posMap.keySet()){
                TonBingTitleConfig titleConfig = titleConfigMap.get(posType).get(posMap.get(posType));
                if (titleConfig != null && titleConfig.getType() == 1) {
                    Map<Long, BigInteger> addMap = userData.getPosAddSilverMap();
                    BigInteger oldValue = addMap.getOrDefault(userId, BigInteger.ZERO);
                    BigInteger userAdd = addValue.multiply(BigInteger.valueOf(titleConfig.getEffect())).divide(BigInteger.valueOf(allAddWeightMap.get(userData.getCampId())));
                    // 累计收取银两
                    userData.setTotalPosSilver(userData.getTotalPosSilver().add(userAdd));
                    addMap.put(userId, oldValue.add(userAdd));
                    userData.setUpdateOption();
                }
            }
        }
    }

    //添加任命完的人的
    private void addNeedSyncPosUser(CrossTonBingUserData userData) {
        synchronized (lock) {
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userData.getUserId());
            if (userBaseInfo != null) {
                if (!needSyncPosUserData.containsKey(userBaseInfo.getServerId())) {
                    needSyncPosUserData.put(userBaseInfo.getServerId(), new ArrayList<>());
                }
                needSyncPosUserData.get(userBaseInfo.getServerId()).add(userData);
            }
        }
    }

    private Map<Long, List<CrossTonBingUserData>> getNeedSyncPosUserDataMap() {
        synchronized (lock) {
            if (needSyncPosUserData.size() == 0) {
                Map<Long, List<CrossTonBingUserData>> tempMap = new ConcurrentHashMap<>();
                Map<Integer,Map<Integer, TonBingTitleConfig>> titleConfigMap = config.getTitleConfigMap();
                for (CrossTonBingUserData userData : userDataMap.values()) {
                    Map<Integer, Integer> posMap = userData.getPositionMap();
                    for(int posType : posMap.keySet()){
                        if (posMap.get(posType) != eTonBingPosition.None.getValue()) {
                            TonBingTitleConfig titleConfig = titleConfigMap.get(userData.getCampId()).get(posMap.get(posType));
                            if (titleConfig.getType() == 1) {
                                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userData.getUserId());
                                if (userBaseInfo != null) {
                                    if (!tempMap.containsKey(userBaseInfo.getServerId())) {
                                        tempMap.put(userBaseInfo.getServerId(), new ArrayList<>());
                                    }
                                    if(!tempMap.get(userBaseInfo.getServerId()).contains(userData)){
                                        tempMap.get(userBaseInfo.getServerId()).add(userData);
                                    }
                                }
                            }
                        }
                    }

                }
                needSyncPosUserData = tempMap;
            }
            return needSyncPosUserData;
        }
    }

    //同步玩家身上的数据
    public void syncUserData(long userId, TonBingProto.TonBingUserDataSyncMsg reqMsg) {
        TonBingProto.TonBingUserDataSyncMsg.Builder respMsg = reqMsg.toBuilder();
        CrossTonBingMatch match = getMatchByUserId(userId);
        //这个版本这个东西没用了，客户端不知道怎么判断了
        respMsg.setWinnerId(0);
        if(match != null){
            respMsg.setMatchId(match.getCrossTonBingData().getMatchId());
            respMsg.setWarType(match.getCrossTonBingData().getWarType());
        }
        sendPacket(ClientProtocol.U_TON_BING_USER_DATA_SYNC, respMsg, userId);
    }
    /**
     * 添加红点
     */
    private void addRedDot(CrossTonBingUserData userData, eTonBingRedDotType type) {
        if (userData.getRedDotMap().containsKey(type.getValue())) {
            return;
        }
        userData.getRedDotMap().put(type.getValue(), System.currentTimeMillis());
        userData.setUpdateOption();

        TonBingProto.TonBingSyncRedDotRespMsg.Builder builder = TonBingProto.TonBingSyncRedDotRespMsg.newBuilder();
        builder.addType(type.getValue());
        sendPacket(ClientProtocol.U_TON_BING_SYNC_RED_DOT, builder, userData.getUserId());
    }

    private CrossTonBingRedPacket oneRedPacket(int campId, long userId, int goodId) {
        CrossTonBingCampData campData = campDataMap.get(campId);
        Map<Long, CrossTonBingRedPacket> redPacketMap = campData.getRedPacketMap();

        CrossTonBingRedPacket redPacket;
        synchronized (lock) {
            // 生成红包
            redPacket = new CrossTonBingRedPacket();
            redPacket.setUserId(userId);
            redPacket.setGoodId(goodId);
            redPacket.setTime(System.currentTimeMillis());
            redPacket.setRedPacketNo(redPacketMap.size() + 1);
            // 加map
            redPacketMap.put(redPacket.getRedPacketNo(), redPacket);
            campData.setUpdateOption();
            // 加统计数量
            addUserRedPacketCount(redPacket, campData);
        }

        return redPacket;
    }

    /**
     * 使用道具后给阵营加红包
     */
    public void addRedPacket(long userId, TonBingProto.CrossTonBingRedPacketAddReqMsg reqMsg) {
        CrossTonBingUserData userData = getUserData(userId);
        if (!isAble(userData)) {
            logger.error("ton bing addRedPacket fail, no able! activityId {}, userId {}.", config.getActivityInfo().getActivityId(), userId);
            return;
        }

        int campId = userData.getCampId();
        CrossTonBingCampData campData = campDataMap.get(campId);
        if (campData == null) {
            logger.error("ton bing addRedPacket fail, no camp data! activityId {}, userId {}.", config.getActivityInfo().getActivityId(), userId);
            return;
        }

        List<CrossTonBingRedPacket> redPacketSyncList = new ArrayList<>();
        synchronized (lock) {
            for (int i = 0; i < reqMsg.getNum(); i++) {
                redPacketSyncList.add(oneRedPacket(campId, userId, reqMsg.getGoodId()));
            }
        }

        if (redPacketSyncList.size() > 0) {
            syncRedPacketToCampUser(userId, redPacketSyncList);

            // 红点
            for (CrossTonBingUserData tmpUserData : userDataMap.values()) {
                if (tmpUserData.getCampId() == campId) {
                    addRedDot(tmpUserData, eTonBingRedDotType.Type9_GetBox);
                }
            }
        }
    }

    // 买完宝箱礼包，同步所有阵营玩家有礼包了
    public void syncRedPacketToCampUser(long userId, List<CrossTonBingRedPacket> redPacketSyncList) {
        CrossTonBingUserData rpUserData = getUserData(userId);
        UserBaseInfo rpUserBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
        if (rpUserBaseInfo == null) {
            return;
        }
        TonBingProto.CrossTonBingRedPacketSyncMsg.Builder syncMsg = TonBingProto.CrossTonBingRedPacketSyncMsg.newBuilder();
        for (CrossTonBingRedPacket redPacket : redPacketSyncList) {
            TonBingProto.TonBingRedPacketMsg.Builder redPacketMsg = TonBingProto.TonBingRedPacketMsg.newBuilder();
            redPacketMsg.setUserId(userId);
            redPacketMsg.setNickName(rpUserBaseInfo.getNickName());
            redPacketMsg.setUnionName(rpUserBaseInfo.getUnionName());
            redPacketMsg.setType(redPacket.getGoodId());
            redPacketMsg.setIsGet(0);
            redPacketMsg.setOrderNo("" + redPacket.getRedPacketNo());
            syncMsg.addRedPackets(redPacketMsg);
        }
        List<Long> serverIdList = new ArrayList<>();
        for (CrossTonBingUserData userData : userDataMap.values()) {
            if (userData.getCampId() == rpUserData.getCampId()) {
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userData.getUserId());
                if (userBaseInfo != null) {
                    syncMsg.addUserIds(userData.getUserId());
                    if (!serverIdList.contains(userBaseInfo.getServerId())) {
                        serverIdList.add(userBaseInfo.getServerId());
                    }
                }
            }
        }
        for (long serverId : serverIdList) {
            //客户端说不用了
//            MessageHelper.sendChannelPacket(serverId, 0, YanQuMessageUtils.buildMessage(GameProtocol.S_CROSS_TON_BING_RED_PACKET_SYNC, syncMsg));
        }
    }

    //同步宝箱值去本服改condition
    public void syncRedPacketBoxValue() {
        if (!ActivityMgr.activityInShowTime(config.getActivityInfo())) {
            return;
        }
        for (CrossTonBingCampData campData : new ConcurrentHashMap<>(campDataMap).values()) {
            if (campData.getRedPacketValue() > 0 && campData.getCampId() != 0) {
                Map<Long, List<Long>> serverUserMap = getCampServerIdUserIdMap(campData.getCampId());
                for (long serverId : serverUserMap.keySet()) {
                    TonBingProto.CrossTonBingRedPacketBoxValueSyncMsg.Builder syncMsg = TonBingProto.CrossTonBingRedPacketBoxValueSyncMsg.newBuilder();
                    syncMsg.setActivityId(campData.getActivityId());
                    for (long userId : serverUserMap.get(serverId)) {
                        syncMsg.addUserIds(userId);
                    }
                    syncMsg.setValue(campData.getRedPacketValue());
                    MessageHelper.sendPacket(serverId, 0, YanQuMessageUtils.buildMessage(GameProtocol.S_CROSS_TON_BING_RED_PACKET_BOX_VALUE_SYNC, syncMsg));
                }
            }
        }
    }
    private Map<Long, List<Long>> getCampServerIdUserIdMap(int campId) {
        Map<Long, List<Long>> resMap = new ConcurrentHashMap<>();
        for (CrossTonBingUserData userData : new ConcurrentHashMap<>(userDataMap).values()) {
            if (userData.getCampId() == campId) {
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userData.getUserId());
                if (userBaseInfo != null) {
                    if (!resMap.containsKey(userBaseInfo.getServerId())) {
                        resMap.put(userBaseInfo.getServerId(), new ArrayList<>());
                    }
                    resMap.get(userBaseInfo.getServerId()).add(userData.getUserId());
                }
            }
        }
        return resMap;
    }

    // 新增玩家的红包宝箱信息
    public void addUserRedPacketCount(CrossTonBingRedPacket redPacket, CrossTonBingCampData campData) {
        Map<Long, CrossTonBingUserRedPacketCount> userRedPacketMap = campData.getUserRedPacketMap();
        if (!userRedPacketMap.containsKey(redPacket.getUserId())) {
            CrossTonBingUserRedPacketCount temp = new CrossTonBingUserRedPacketCount();
            temp.setUserId(redPacket.getUserId());
            userRedPacketMap.put(redPacket.getUserId(), temp);
        }
        CrossTonBingUserRedPacketCount userRedPacket = userRedPacketMap.get(redPacket.getUserId());
        Map<Integer, Integer> redPacketCountMap = userRedPacket.getUserRedPacketCountMap();
        redPacketCountMap.put(redPacket.getGoodId(), redPacketCountMap.getOrDefault(redPacket.getGoodId(), 0) + 1);
        userRedPacket.setUserRedPacketCountMap(redPacketCountMap);
    }

    /**
     * 获取红包列表（优先没领取的）
     */
    public void getRedPacketList(long userId) {
        TonBingProto.TonBingRedPacketGetListRespMsg.Builder respMsg = TonBingProto.TonBingRedPacketGetListRespMsg.newBuilder();
        respMsg.setRet(0);

        CrossTonBingUserData userData = getUserData(userId);
        int campId = userData.getCampId();

        // 没资格
        if (!isAble(userData)) {
            respMsg.setRet(GameErrorCode.E_TON_BING_NO_ABLE);
            sendPacket(ClientProtocol.U_TON_BING_RED_PACKET_LIST, respMsg, userId);
            return;
        }

        // 统计红包
        LinkedList<CrossTonBingRedPacket> noGetRewardList = new LinkedList<>();
        LinkedList<CrossTonBingRedPacket> getRewardList = new LinkedList<>();
        CrossTonBingCampData campData = campDataMap.get(campId);
        if (campData != null) {
            for (CrossTonBingRedPacket redPacket : campData.getRedPacketMap().values()) {
                if (redPacket.getGetRewardUserList().contains(userId)) {
                    getRewardList.add(redPacket);
                } else {
                    noGetRewardList.add(redPacket);
                }
            }
        }

        // 发送晚的在前
        noGetRewardList.sort(new RedPacketSort());
        getRewardList.sort(new RedPacketSort());

        // 拿前50个
        int maxNum = 50;
        int num = 1;
        for (CrossTonBingRedPacket redPacket : noGetRewardList) {
            if (num >= maxNum) {
                break;
            }
            respMsg.addRedPackets(parseTonBingRedPacketMsg(redPacket, false));
            num++;
        }
        for (CrossTonBingRedPacket redPacket : getRewardList) {
            if (num >= maxNum) {
                break;
            }
            respMsg.addRedPackets(parseTonBingRedPacketMsg(redPacket, true));
            num++;
        }

        sendPacket(ClientProtocol.U_TON_BING_RED_PACKET_LIST, respMsg, userId);
    }

    public void getBattleInfo(long userId) {
        checkPatrons(userId);
        TonBingProto.TonBingGetBattleInfoRespMsg.Builder respMsg = TonBingProto.TonBingGetBattleInfoRespMsg.newBuilder();
        int turn = config.getTurn();
        long nowTime = System.currentTimeMillis();
        if(nowTime > config.getActivityInfo().getEndTime() * 1000){
            turn = config.getLastTurn();
        }
        List<Integer> warTypeList = config.getWarTypeList();
        Map<Integer,Map<Integer,CrossTonBingMatch>> turnMap = turnMatchMap.get(turn);
        for(int warType : warTypeList){
            TonBingProto.TonBingBattleInfoTempMsg.Builder tmpMsg = TonBingProto.TonBingBattleInfoTempMsg.newBuilder();
            tmpMsg.setWarType(warType);
            tmpMsg.setUnionCount(0);
            if(turnMap != null && turnMap.containsKey(warType)){
                int unionCount = 0;
                for(CrossTonBingMatch match : turnMap.get(warType).values()){
                    tmpMsg.addMatchId(match.getCrossTonBingData().getMatchId());
                    unionCount += match.getUnionJoinMap().size();
                }
                tmpMsg.setUnionCount(unionCount);
            }
            respMsg.addInfo(tmpMsg);
        }
        sendPacket(ClientProtocol.U_TON_BING_BATTLE_INFO, respMsg, userId);
    }

    public void getTodayRankInfo(long userId) {
        TonBingProto.TonBingGetTodayRankRespMsg.Builder respMsg = TonBingProto.TonBingGetTodayRankRespMsg.newBuilder();
        respMsg.setRet(0);
        int nowTurn = config.getTurn();
        long nowTime = System.currentTimeMillis();
        if (nowTime > config.getActivityInfo().getEndTime() * 1000) {
            nowTurn = config.getLastTurn();
        }
        for (CrossTonBingMatch match : matchMap.values()) {
            if (match.getCrossTonBingData().getTurn() != nowTurn) continue;
            respMsg.addList(match.getCampUnionRankToday(userId));
        }
        sendPacket(ClientProtocol.U_TON_BING_TODAY_RANK, respMsg, userId);
    }

    public String getUserAreaParam(long userId) {
        CrossTonBingUserData userData = userDataMap.get(userId);
        if (userData == null) {
            return null;
        }

        CrossTonBingMatch match = getMatchByUserId(userId);
        if (match == null) {
            return null;
        }

        Map<Integer, Map<Integer, CrossTonBingMatch>> warTypeMap = turnMatchMap.get(match.getCrossTonBingData().getTurn());
        if (warTypeMap == null) {
            return null;
        }

        Map<Integer, CrossTonBingMatch> tempMatchMap = warTypeMap.get(match.getCrossTonBingData().getWarType());
        if (tempMatchMap == null) {
            return null;
        }

        List<CrossTonBingMatch> tempList = new ArrayList<>(tempMatchMap.values());

        int groupId = 0;
        for (int i = 0; i < tempList.size(); i++) {
            if (match.getCrossTonBingData().getMatchId() == tempList.get(i).getCrossTonBingData().getMatchId()) {
                groupId = i + 1;
                break;
            }
        }

        JSONObject json = new JSONObject();
        json.put("area", getNowWarType(userData.getUnionUid()));
        json.put("group", groupId);
        return json.toJSONString();
    }

    @Override
    public BigDecimal calcMemberCompressedAbility(long avgAbility, int unionMemberNum, List<Long> abilityParams) {
        long p0 = abilityParams.get(0);
        long p1 = abilityParams.get(1);
        long p2 = abilityParams.get(2);
        long p3 = abilityParams.get(3);
        if (p0 <= 5 && p1 <= 2 && p2 <= 5 && p3 <= 5) {
            // 利用公式对总赚钱进行战力压缩
            // x = p0√totalAbility * memberNum   y = (x^p1) / p2 - p3 * x
            BigDecimal x = BigDecimal.valueOf(Math.pow(avgAbility,
                    1.0 / p0)).multiply(BigDecimal.valueOf((unionMemberNum)));
            return BigDecimal.valueOf(Math.pow(x.doubleValue(), p1)).divide(BigDecimal.valueOf(p2), 8, RoundingMode.HALF_UP)
                    .subtract(BigDecimal.valueOf(p3).multiply(x));
        } else if (p0 > 5 && p1 > 2 && p2 > 5 && p3 >= 5) {
            // 利用公式对总赚钱进行战力压缩  v = log(p2)(totalAbility / p0 * p1) * p3 * memberNum;
            BigDecimal tmp = BigDecimal.valueOf(avgAbility).divide(BigDecimal.valueOf(p0), 9, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(p1));
            BigDecimal tmp1 = BigDecimal.valueOf(Math.log(tmp.doubleValue())).divide(BigDecimal.valueOf(Math.log(p2)), 9, RoundingMode.HALF_UP);
            return tmp1.multiply(BigDecimal.valueOf(p3)).multiply(BigDecimal.valueOf(unionMemberNum));
        }

        return null;
    }

    @Override
    public void initUserData(long userId) {
        // 生成userData
        if (!userDataMap.containsKey(userId)) {
            synchronized (userDataMap) {
                if (!userDataMap.containsKey(userId)) {
                    CrossTonBingUserData userData = CrossTonBingUserData.initCrossTonBingUserData(config.getActivityInfo().getActivityId(), userId);

                    // 初始化兵营部分数据
                    CrossTonBingBarracks barracks = userData.getBarracks();
                    barracks.setHospitalSize(config.getWoundedSoldierMaxNum());
                    barracks.setRescueSpeed(config.getWoundedRescueTime());
                    barracks.setRescueCount(config.getWoundedRescueCount());
                    userData.setUpdateOption();

                    // 加到map
                    userDataMap.put(userId, userData);
                }
            }
        }
    }

    @Override
    public List<CampUnion> resort(List<CampUnion> campUnions) {
        return campUnions.stream().filter(p -> p instanceof CrossTonBingUnionJoin)
                .map(p -> (CrossTonBingUnionJoin) p).sorted((o1, o2) -> {
                    if (o1.getCompressedAbility().compareTo(o2.getCompressedAbility()) == 0) { // 压缩战力一致，比较oldRank
                        return Integer.compare(o1.getOldRank(), o2.getOldRank());
                    }
                    return o2.getCompressedAbility().compareTo(o1.getCompressedAbility());
                }).collect(Collectors.toList());
    }

    @Override
    public void setUnionJoinCamp(CampUnion campUnion, int campId) {
        if (campUnion == null) {
            return;
        }

        campUnion.setCampId(campId);

//        CrossTonBingUnionJoin union = (CrossTonBingUnionJoin) campUnion;
//        Map<Long, CrossTonBingUnionJoinMember> memberMap = union.getMemberMap();
//        if (memberMap == null || memberMap.isEmpty()) {
//            logger.error("活动:{} 商会:{} 分阵营时，商会成员为空", config.getActivityInfo().getActivityId(), union.getUnionUid());
//        }
//        for (CrossTonBingUnionJoinMember member : union.getMemberMap().values()) {
//            CrossTonBingUserData userData = getUserData(member.getUserId());
//            if (userData != null) {
//                userData.setCampId(campId);
//                userData.setUnionUid(union.getUnionUid());
//            }
//        }
    }

    class RedPacketSort implements Comparator<CrossTonBingRedPacket> {
        @Override
        public int compare(CrossTonBingRedPacket o1, CrossTonBingRedPacket o2) {
            return Long.compare(o2.getTime(), o1.getTime());
        }
    }

    /**
     * 初始化各阵营红包排行
     */
    public void initUserRedPacketNumMap() {
        for (CrossTonBingCampData campData : campDataMap.values()) {
            Map<Long, CrossTonBingUserRedPacketCount> tempMap = new ConcurrentHashMap<>();
            for (CrossTonBingRedPacket redPacket : campData.getRedPacketMap().values()) {
                if (!tempMap.containsKey(redPacket.getUserId())) {
                    CrossTonBingUserRedPacketCount temp = new CrossTonBingUserRedPacketCount();
                    temp.setUserId(redPacket.getUserId());
                    tempMap.put(redPacket.getUserId(), temp);
                }
                CrossTonBingUserRedPacketCount userRedPacketCount = tempMap.get(redPacket.getUserId());
                Map<Integer, Integer> redPacketCountMap = userRedPacketCount.getUserRedPacketCountMap();
                redPacketCountMap.put(redPacket.getGoodId(), redPacketCountMap.getOrDefault(redPacket.getGoodId(), 0) + 1);
                userRedPacketCount.setUserRedPacketCountMap(redPacketCountMap);
            }
            campData.setUserRedPacketMap(tempMap);
        }
    }


    /**
     * 红包发送记录
     */
    public void getRedPacketRecord(long userId) {
        TonBingProto.TonBingRedPacketGetRecordRespMsg.Builder respMsg = TonBingProto.TonBingRedPacketGetRecordRespMsg.newBuilder();
        respMsg.setRet(0);

        CrossTonBingUserData userData = getUserData(userId);
        if (!isAble(userData)) {
            respMsg.setRet(GameErrorCode.E_TON_BING_NO_ABLE);
            sendPacket(ClientProtocol.U_TON_BING_RED_PACKET_RECORD_LIST, respMsg, userId);
            return;
        }

        CrossTonBingCampData campData = campDataMap.get(userData.getCampId());
        if (campData != null) {
            Map<Long, CrossTonBingUserRedPacketCount> userRedPacketMap = campData.getUserRedPacketMap();
            for (CrossTonBingUserRedPacketCount userRedPacket : userRedPacketMap.values()) {
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userRedPacket.getUserId());
                if (userBaseInfo == null) {
                    userBaseInfo = new UserBaseInfo();
                }

                TonBingProto.TonBingRedPacketRankMsg.Builder rankTempMsg = TonBingProto.TonBingRedPacketRankMsg.newBuilder();
                rankTempMsg.setUserId(userRedPacket.getUserId());
                rankTempMsg.setNickName(userBaseInfo.getNickName());
                for (Map.Entry<Integer, Integer> entry : userRedPacket.getUserRedPacketCountMap().entrySet()) {
                    TonBingProto.TonBingRedPacketBoxMsg.Builder boxTempMsg = TonBingProto.TonBingRedPacketBoxMsg.newBuilder();
                    boxTempMsg.setBoxKey(entry.getKey());
                    boxTempMsg.setNum(entry.getValue());
                    rankTempMsg.addBox(boxTempMsg);
                }
                respMsg.addRecords(rankTempMsg);
            }
        }

        sendPacket(ClientProtocol.U_TON_BING_RED_PACKET_RECORD_LIST, respMsg, userId);
    }


    /**
     * 领取阵营宝箱
     */
    public void getRedPacketBox(long userId, TonBingProto.CrossTonBingRedPacketGetBoxReqMsg reqMsg) {
        TonBingProto.CrossTonBingRedPacketGetBoxRespMsg.Builder serverMsg = TonBingProto.CrossTonBingRedPacketGetBoxRespMsg.newBuilder();
        serverMsg.setRet(0);

        // 资格
        CrossTonBingUserData userData = getUserData(userId);
        if (!isAble(userData)) {
            serverMsg.setRet(GameErrorCode.E_TON_BING_NO_ABLE);
            sendPacket(GameProtocol.S_CROSS_TON_BING_RED_PACKET_GET_BOX, serverMsg, userId);
            return;
        }

        // 数据判断
        CrossTonBingCampData campData = campDataMap.get(userData.getCampId());
        if (campData == null) {
            serverMsg.setRet(GameErrorCode.E_TON_BING_RED_PACKET_IS_GET);
            sendPacket(GameProtocol.S_CROSS_TON_BING_RED_PACKET_GET_BOX, serverMsg, userId);
            return;
        }

        long boxNo = StringUtils.isNullOrEmpty(reqMsg.getOrderNo()) ? 0 : Long.valueOf(reqMsg.getOrderNo());
        Map<Integer, TonBingCampBoxConfig> campBoxConfigMap = config.getCampBoxConfigMap();
        Map<Long, CrossTonBingRedPacket> redPacketMap = campData.getRedPacketMap();

        synchronized (lock) {

            if (boxNo == 0) {
                // 【一键领取】
                Property reward = new Property();
                for (CrossTonBingRedPacket redPacket : redPacketMap.values()) {
                    Set<Long> getRewardUserList = redPacket.getGetRewardUserList();
                    if (!getRewardUserList.contains(userId)) {
                        TonBingCampBoxConfig campBoxConfig = campBoxConfigMap.get(redPacket.getGoodId());
                        reward.addProperty(campBoxConfig.getBoxId(), BigInteger.ONE);
                        getRewardUserList.add(userId);
                        campData.setRedPacketValue(campData.getRedPacketValue() + campBoxConfig.getBoxScore());
                    }
                }
                String rewardStr = PropertyHelper.parsePropertyToString(reward);
                if (StringUtils.isNullOrEmpty(rewardStr)) {
                    serverMsg.setRet(GameErrorCode.E_TON_BING_RED_PACKET_IS_GET);
                    sendPacket(GameProtocol.S_CROSS_TON_BING_RED_PACKET_GET_BOX, serverMsg, userId);
                    return;
                }
                serverMsg.setReward(rewardStr);
                sendPacket(GameProtocol.S_CROSS_TON_BING_RED_PACKET_GET_BOX, serverMsg, userId);
                campData.setUpdateOption();
            } else {
                // 【单个领取】
                CrossTonBingRedPacket redPacket = redPacketMap.get(boxNo);
                if (redPacket == null) {
                    serverMsg.setRet(GameErrorCode.E_TON_BING_RED_PACKET_NO_EXIT);
                    sendPacket(GameProtocol.S_CROSS_TON_BING_RED_PACKET_GET_BOX, serverMsg, userId);
                    return;
                }
                Set<Long> getRewardList = redPacket.getGetRewardUserList();
                if (getRewardList.contains(userId)) {
                    serverMsg.setRet(GameErrorCode.E_TON_BING_RED_PACKET_IS_GET);
                    sendPacket(GameProtocol.S_CROSS_TON_BING_RED_PACKET_GET_BOX, serverMsg, userId);
                    return;
                }
                TonBingCampBoxConfig campBoxConfig = campBoxConfigMap.get(redPacket.getGoodId());
                getRewardList.add(userId);
                campData.setRedPacketValue(campData.getRedPacketValue() + campBoxConfig.getBoxScore());
                serverMsg.setReward(campBoxConfig.getBoxId() + "=1");
                // 一键领取的时候还要下去连大宝箱都领了
                serverMsg.setBoxValue(campData.getRedPacketValue());
                serverMsg.setActivityId(config.getActivityInfo().getActivityId());
                sendPacket(GameProtocol.S_CROSS_TON_BING_RED_PACKET_GET_BOX, serverMsg, userId);
                campData.setUpdateOption();
            }
        }
    }

    @Override
    public CrossTonBingUserData getUserData(long userId) {
        initUserData(userId);
        return userDataMap.get(userId);
    }

    public CrossTonBingUnionJoin getUnionJoin(String unionUid) {
        return unionJoinMap.get(unionUid);
    }

    public CrossTonBingDataMain getCrossTonBingDataMain() {
        return crossTonBingDataMain;
    }

    // ============================== 定时器 ==============================

    /**
     * 初始化所有Task
     */
    public void initTask() {

        // 商会报名锁定
        long checkLockTime = Math.min(System.currentTimeMillis(), config.getJoinTimeList().get(1)); // 锁名单前，要检查下其他数据
        addTask(new CrossTonBingLockUnionTask(this, checkLockTime));
        long makeMatchStartTime = Math.min(System.currentTimeMillis(), config.getJoinTimeList().get(1) + 10000); // 开始生成比赛时间
        addTask(new CrossTonBingMakeMatchTask(this, makeMatchStartTime));

        addTask(new CrossTonBingSetWinnerTask(this, config.getActivityInfo().getEndTime() * 1000L));
    }

    //锁定玩排行榜设置商会信息
    public void lockUnionMsg(RankProto.CrossUnionRankListLockMsg lockMsg) {

        List<Long> syncList = new ArrayList<>();

        synchronized (lock) {

            // 时间
            boolean lockUnion = getCrossTonBingDataMain().isLockUnion();
            boolean activityEnd = System.currentTimeMillis() > config.getActivityInfo().getEndTime() * 1000L;

            // 结束了就无法操作了
            if (activityEnd) {
                return;
            }

            // 自动报名数据（这里还是按赚速，拿不到最高赚钱）
            List<RankProto.CrossUnionRankLockTemp> rankList = lockMsg.getRankList();

            // 遍历数据一个个处理
            int i = 0;//加入计数
            for (RankProto.CrossUnionRankLockTemp unionMsg : rankList) {
                if(i < config.getUnionNum()){
                    // 【商会处理】
                    CrossTonBingUnionJoin join = unionJoinMap.get(unionMsg.getRankTemp().getUnionUid());
                    if (join == null) {
                        if (!lockUnion) {
                            join = new CrossTonBingUnionJoin();
                            join.setActivityId(config.getActivityInfo().getActivityId());
                            join.setUnionUid(unionMsg.getRankTemp().getUnionUid());
                            join.setUnionBaseInfo(UnionBasePb.parseUnionBaseInfo(unionMsg.getRankTemp().getUnionBaseData()));
                            join.setMemberMap(new ConcurrentHashMap<Long, CrossTonBingUnionJoinMember>());
                            //已经拉过来是多少就是多少了，不用再去本服更新来更新去了，这个已经是历史最高赚钱了
                            join.setTotalAbility(Long.valueOf(unionMsg.getRankTemp().getValue()));
                            join.setInsertOption();
                            unionJoinMap.put(join.getUnionUid(), join);
                        }
                    }
                    if (join == null) {
                        continue;
                    }

                    // 【成员处理】
                    Map<Long, CrossTonBingUnionJoinMember> oldMap = join.getMemberMap();
                    if (!lockUnion) {
                        Map<Long, CrossTonBingUnionJoinMember> memberMap = new ConcurrentHashMap<>();
                        for (RankProto.CrossUnionMemberTemp msg : unionMsg.getMemberList()) {
                            CrossTonBingUnionJoinMember member = oldMap.remove(msg.getMemberId());
                            if (member == null) {
                                member = new CrossTonBingUnionJoinMember(msg.getMemberId(), msg.getServerId());
                                syncList.add(member.getUserId()); // 添加报名状态同步
                            }
                            member.setTopAbility(Long.parseLong(msg.getMaxAbility()));
//                            member.setPosition(msg.getPosition());
                            memberMap.put(member.getUserId(), member);
                        }
                        join.setMemberMap(memberMap);
                        syncList.addAll(oldMap.keySet()); // 添加报名状态同步
                    } else {
                        for (RankProto.CrossUnionMemberTemp msg : unionMsg.getMemberList()) {
                            CrossTonBingUnionJoinMember member = oldMap.get(msg.getMemberId());
                            if (member != null) {
//                            member.setPosition(msg.getPosition());
                            }
                        }
                    }
                    join.setUpdateOption();
                }
                // 日志
                CrossAutoLogMgr.add(new LogTonBingJoin(
                        config.getActivityInfo().getActivityId(),
                        -1,
                        unionMsg.getRankTemp().getUnionUid(),
                        i < config.getUnionNum()?1:0,
                        unionMsg.getRankTemp().getValue()
                ));
                i++;
            }
        }

        // 同步报名状态
        for (Long userId : syncList) {
            syncBaseDataMsg(getUserData(userId));
        }

        // 没赚钱的拉一下
        if (!getCrossTonBingDataMain().isLockUnion()) {
            List<String> unionIdList = new ArrayList<>();
            for (RankProto.CrossUnionRankLockTemp unionMsg : lockMsg.getRankList()) {
                checkUnionJoinMember(unionMsg.getRankTemp().getUnionUid());
                //去跨服拉一下职位，没职位我日
                unionIdList.add(unionMsg.getRankTemp().getUnionUid());
            }
            sendGetUnionMsg(1, unionIdList, 0);

        }

    }

    /**
     * 商会报名、锁名单 任务
     */
    public void crossTonBingLockUnionTask() {
        // 【已经锁名单了】
        if (getCrossTonBingDataMain().isLockUnion()) {
            return;
        }

        long now = System.currentTimeMillis();

        // 报名期结束 锁定商会名单
        if (now > config.getJoinTimeList().get(1)) {
            logger.error("巅峰统兵请求榜单锁定");
            List<Long> serverList = config.getActivityInfo().getServerIdList();
            int index = randomHelper.next(0,serverList.size());
            long serverId = serverList.get(index);
            //报名期结算就去拉取有资格的商会
            MessageHelper.sendPacket(serverId, 0,
                    YanQuMessageUtils.buildMessage(GameProtocol.S_PEAK_UNION_MAX_ABILITY_RANK_LOCK,
                            CommonActivityProto.CommonActivityRankListReqMsg.newBuilder().setGroupId(UnionActivityGroupHelper.NO_NEED_GROUP_ID).setActivityId(config.getActivityInfo().getActivityId())));
            //需要快速请求本服的判断两秒就算过期的
            long next10Second = System.currentTimeMillis() + DateHelper.SECOND_MILLIONS;
            addTask(new CrossTonBingLockUnionTask(this, next10Second));
        }else{
            // 【没锁名单】先把任务加回去比较稳
            long next10Second = System.currentTimeMillis() + DateHelper.SECOND_MILLIONS * 10;
            addTask(new CrossTonBingLockUnionTask(this, next10Second));
        }
    }

    /**
     * 没数据的成员拉一下
     *
     * @param optionalUnionUid 可以为null，就检查全部商会
     */
    private boolean checkUnionJoinMember(String optionalUnionUid) {
        // 检查报名的商会中，区服未上传数据的成员
        Map<Long, List<Long>> serverUserMap = new ConcurrentHashMap<>();
        for (CrossTonBingUnionJoin unionJoin : unionJoinMap.values()) {
            if (optionalUnionUid != null && !Objects.equals(unionJoin.getUnionUid(), optionalUnionUid)) {
                continue;
            }
            for (CrossTonBingUnionJoinMember joinMember : unionJoin.getMemberMap().values()) {
                if (joinMember.getEarnSpeed() == 0 || joinMember.getTopAbility() == 0) {
                    serverUserMap.putIfAbsent(joinMember.getServerId(), new ArrayList<>());
                    serverUserMap.get(joinMember.getServerId()).add(joinMember.getUserId());
                }
            }
        }
        boolean suc = true;
        for (Map.Entry<Long, List<Long>> entry : serverUserMap.entrySet()) {
            long serverId = entry.getKey();
            List<Long> userId = entry.getValue();
            if (userId.size() > 0) {
                sendGetUnionMemberMsg(serverId, userId);
                suc = false;
            }
        }
        return suc;
    }


    // ============================== 榜单 ==============================

    /**
     * 初始化全部榜单
     */
    private void initAllRankList() {
        CrossTonBingRankListModel userModel = new CrossTonBingRankListModel();
        Map<Integer, CrossTonBingRankListModel> campUserMap = new ConcurrentHashMap<>();
        Map<Integer, CrossTonBingRankListModel> campUnionMap = new ConcurrentHashMap<>();

        for (CrossTonBingUserData userData : userDataMap.values()) {
            if (isAble(userData)) {
                CrossTonBingRank rank = new CrossTonBingRank(String.valueOf(userData.getUserId()), userData.getZhanGong(), userData.getZhanGongTime());
                // 【个人榜】
                userModel.rankChange(rank);
                // 【阵营内个人榜】
                campUserMap.putIfAbsent(userData.getCampId(), new CrossTonBingRankListModel());
                campUserMap.get(userData.getCampId()).rankChange(rank);
            }
        }


        for (CrossTonBingUnionJoin join : unionJoinMap.values()) {
            if (join.getCampId() != 0) {
                // 【阵营内商会榜】
                campUnionMap.putIfAbsent(join.getCampId(), new CrossTonBingRankListModel());
                CrossTonBingRank rank = getUnionZhanGongRank(join);
                campUnionMap.get(join.getCampId()).rankChange(rank);
            }
        }

        userRank = userModel;
        campUserRankMap = campUserMap;
        campUnionRankMap = campUnionMap;
        //asdasd商会榜才整个战场吧，提出来，乱的一比
    }

    public void rankZhanGong(long userId,long battleTime) {
        CrossTonBingUserData userData = getUserData(userId);

        // 个人榜
        CrossTonBingRank rank = new CrossTonBingRank(String.valueOf(userId), userData.getZhanGong(), battleTime);
        userRank.rankChange(rank);

        // 阵营内个人榜
        campUserRankMap.putIfAbsent(userData.getCampId(), new CrossTonBingRankListModel());
        campUserRankMap.get(userData.getCampId()).rankChange(rank);

        // 阵营内商会榜
        CrossTonBingUnionJoin join = unionJoinMap.get(userData.getUnionUid());
        if (join != null) {
            long unionValue = 0;
            for (long memberId : join.getMemberMap().keySet()) {
                CrossTonBingUserData memberData = getUserData(memberId);
                unionValue += memberData.getZhanGong();
            }

            CrossTonBingRank unionRank = new CrossTonBingRank(join.getUnionUid(), unionValue, battleTime);
            if (join.getTotalAbility() == 0L) {
                join.reCalcAbility();
            }
            unionRank.setAbility(join.getTotalAbility());
            //商会排行榜还要战场排，其他搞不懂，先没有吧，太乱了
            unionRank.setWarType(getNowWarType(unionRank.getId()));

            campUnionRankMap.putIfAbsent(userData.getCampId(), new CrossTonBingRankListModel());
            campUnionRankMap.get(userData.getCampId()).rankChange(unionRank);
        }
    }

    /**
     * 获取商会战功Rank
     */
    private CrossTonBingRank getUnionZhanGongRank(CrossTonBingUnionJoin join) {
        long unionValue = 0;
        long maxTime = 0;
        for (long memberId : join.getMemberMap().keySet()) {
            CrossTonBingUserData memberData = getUserData(memberId);
            unionValue += memberData.getZhanGong();
            maxTime = Math.max(maxTime, memberData.getZhanGongTime());
        }

        CrossTonBingRank rank = new CrossTonBingRank(join.getUnionUid(), unionValue, maxTime);
        if (join.getTotalAbility() == 0L) {
            join.reCalcAbility();
        }
        rank.setAbility(join.getTotalAbility());
        rank.setWarType(getNowWarType(join.getUnionUid()));

        return rank;
    }

    // ============================== 战斗 ==============================

    // ============================== 报名 ==============================

    /**
     * 请求商会跨服拿成员数据
     *
     * @param type     1根据unionUid，2根据数量
     * @param unionUid 不需要可以空list
     * @param count    不需要就传0
     */
    public void sendGetUnionMsg(int type, List<String> unionUid, int count) {
        TonBingProto.CrossTonBingGetUnionReqMsg.Builder builder = TonBingProto.CrossTonBingGetUnionReqMsg.newBuilder();
        builder.setActivityId(config.getActivityInfo().getActivityId());
        List<Long> serverIdList = config.getActivityInfo().getServerIdList();
        builder.setGameServerId(serverIdList.get(new Random().nextInt(serverIdList.size())));
        builder.setType(type);
        if (type == 1) {
            for (String s : unionUid) {
                builder.addUnionUid(s);
            }
        } else if (type == 2) {
            builder.setEarnSpeedTopCount(count);
            builder.addAllServerId(config.getActivityInfo().getServerIdList());
        }
        MessageHelper.sendPacket(builder.getGameServerId(), 0, YanQuMessageUtils.buildMessage(CrossProtocol.C3_CROSS_TON_BING_GET_UNION_REQ, builder));
    }

    public void updateUnionByCmd(TonBingProto.CrossTonBingGetUnionRespMsg reqMsg) {

        List<Long> syncList = new ArrayList<>();

        synchronized (lock) {

            // 时间
            boolean lockUnion = getCrossTonBingDataMain().isLockUnion();
            boolean activityEnd = System.currentTimeMillis() > config.getActivityInfo().getEndTime() * 1000L;

            // 结束了就无法操作了
            if (activityEnd) {
                return;
            }

            // 自动报名数据（这里还是按赚速，拿不到最高赚钱）
            boolean autoJoin = reqMsg.getType() == 2;
            List<TonBingProto.TonBingUnionMsg> rankList = reqMsg.getUnionList().stream().sorted(new Comparator<TonBingProto.TonBingUnionMsg>() {
                @Override
                public int compare(TonBingProto.TonBingUnionMsg o1, TonBingProto.TonBingUnionMsg o2) {
                    BigInteger bigInt1 = new BigInteger(o1.getUnionInfo().getTotalEarnSpeed());
                    BigInteger bigInt2 = new BigInteger(o2.getUnionInfo().getTotalEarnSpeed());
                    return bigInt2.compareTo(bigInt1);
                }
            }).collect(Collectors.toList());

            // 遍历数据一个个处理
            for (TonBingProto.TonBingUnionMsg unionMsg : rankList) {

                // 【商会处理】
                CrossTonBingUnionJoin join = unionJoinMap.get(unionMsg.getUnionUid());
                if (join == null) {
                    // 自动报名 && 未锁名单 && 有空位
                    if (autoJoin && !lockUnion && unionJoinMap.size() < config.getUnionNum()) {
                        join = new CrossTonBingUnionJoin();
                        join.setActivityId(config.getActivityInfo().getActivityId());
                        join.setUnionUid(unionMsg.getUnionUid());
                        join.setUnionBaseInfo(UnionBasePb.parseUnionBaseInfo(unionMsg.getUnionInfo()));
                        join.setMemberMap(new ConcurrentHashMap<Long, CrossTonBingUnionJoinMember>());
                        join.setInsertOption();
                        unionJoinMap.put(join.getUnionUid(), join);
                    }
                }else{
                    join.setUnionBaseInfo(UnionBasePb.parseUnionBaseInfo(unionMsg.getUnionInfo()));
                }
                if (join == null) {
                    continue;
                }

                // 【成员处理】
                Map<Long, CrossTonBingUnionJoinMember> oldMap = join.getMemberMap();
                if (!lockUnion) {
                    Map<Long, CrossTonBingUnionJoinMember> memberMap = new ConcurrentHashMap<>();
                    for (TonBingProto.TonBingUnionMemberInfoMsg msg : unionMsg.getMemberList()) {
                        CrossTonBingUnionJoinMember member = oldMap.remove(msg.getUserId());
                        if (member == null) {
                            member = new CrossTonBingUnionJoinMember(msg.getUserId(), msg.getServerId());
                            syncList.add(member.getUserId()); // 添加报名状态同步
                        }
                        member.setPosition(msg.getPosition());
                        memberMap.put(member.getUserId(), member);
                    }
                    join.setMemberMap(memberMap);
                    syncList.addAll(oldMap.keySet()); // 添加报名状态同步
                } else {
                    for (TonBingProto.TonBingUnionMemberInfoMsg msg : unionMsg.getMemberList()) {
                        CrossTonBingUnionJoinMember member = oldMap.get(msg.getUserId());
                        if (member != null) {
                            member.setPosition(msg.getPosition());
                        }
                    }
                }
                join.setUpdateOption();
            }
        }

        // 同步报名状态
        for (Long userId : syncList) {
            syncBaseDataMsg(getUserData(userId));
        }

        // 没赚钱的拉一下
        if (!getCrossTonBingDataMain().isLockUnion()) {
            for (TonBingProto.TonBingUnionMsg unionMsg : reqMsg.getUnionList()) {
                checkUnionJoinMember(unionMsg.getUnionUid());
            }
        }

    }


    /**
     * 请求游戏服上传玩家信息
     */
    private void sendGetUnionMemberMsg(long serverId, List<Long> userId) {
        TonBingProto.CrossTonBingGetMemberReqMsg.Builder builder = TonBingProto.CrossTonBingGetMemberReqMsg.newBuilder();
        builder.setActivityId(config.getActivityInfo().getActivityId());
        builder.addAllUserId(userId);
        MessageHelper.sendPacket(serverId, 0, YanQuMessageUtils.buildMessage(GameProtocol.S_CROSS_TON_BING_GET_UNION_MEMBER_REQ, builder));
    }

    /**
     * 锁定商会
     */
    public void lockUnion(RankProto.CrossUnionRankListLockMsg lockMsg) {
        synchronized (lock) {
            lockUnionMsg(lockMsg);
            if (getCrossTonBingDataMain().isLockUnion()) {
                return;
            }

            // 缓存一下门客赚钱,不用缓存了，没有了，有对应赚钱的排行榜了
            /*for (CrossTonBingUnionJoin join : unionJoinMap.values()) {
                join.reCalcAbility();
            }*/

            // 排序拿前几名
            List<CrossTonBingUnionJoin> rankList = unionJoinMap.values().stream()
                    .sorted(new Comparator<CrossTonBingUnionJoin>() {
                        @Override
                        public int compare(CrossTonBingUnionJoin o1, CrossTonBingUnionJoin o2) {
                            // 922 3372 0368亿
                            return Long.compare(o2.getTotalAbility(), o1.getTotalAbility());
                        }
                    })
                    .limit(config.getUnionNum())
                    .collect(Collectors.toList());

            for (int i = 0; i < rankList.size(); i++) { // 总赚钱排名
                CrossTonBingUnionJoin union = rankList.get(i);
                union.setOldRank(i + 1);
            }

            // 分阵营
            List<Long> abilityParams = config.getGuildGroupRuleParams();
            List<Integer> groupParams = config.getGroupParams();
            if (abilityParams.isEmpty() || groupParams.isEmpty()) { // 如果未配置战力压缩规则或特殊分组范围，就走旧的分配阵营逻辑
                lockCamp(rankList);
            } else {
                List<Integer> secondMatchRanges = config.secondMatchRanges();
                if (abilityParams.isEmpty() || secondMatchRanges.isEmpty()) {
                    logger.error("巅峰统兵 activity {} union lock error. 商会分组范围参数或者战力压缩参数没配置", config.getActivityInfo().getActivityId());
                    return;
                }
                lockCamp(rankList, secondMatchRanges, abilityParams);
            }

            //打补丁
            for (CrossTonBingUnionJoin union : unionJoinMap.values()) {
                if (union.getCampId() == 0) {
                    logger.error("巅峰统兵campId为0,activityId={},unionUid={}", config.getActivityInfo().getActivityId(),union.getUnionUid());
                    continue;
                }

                for (CrossTonBingUnionJoinMember unionMember : union.getMemberMap().values()) {
                    CrossTonBingUserData userData = getUserData(unionMember.getUserId());
                    userData.setCampId(union.getCampId());
                    userData.setUnionUid(union.getUnionUid());
                }
            }

            // 改状态
            getCrossTonBingDataMain().setLockUnion(true);
            logger.error("tonbing activity {} lock union.", config.getActivityInfo().getActivityId());


            // 移动玩家到起始点 到对应的比赛中去做这件事情了
//            crossTonBingInitTeamPosTask();

            // 初始化榜单，让0值的也上榜，才能看到自己阵营都有谁
            initAllRankList();

            // 同步状态
            for (CrossTonBingUserData userData : userDataMap.values()) {
                syncBaseDataMsg(userData);
                // 跨服同步用户数据到游戏服
                syncUserDataToGameServer(userData,false);
            }
        }

        // 日志
        for (CrossTonBingUnionJoin join : unionJoinMap.values()) {
            CrossAutoLogMgr.add(new LogTonBingLockUnion(
                    config.getActivityInfo().getActivityId(),
                    join.getUnionUid(),
                    join.getCampId(),
                    join.getUnionBaseInfo().getTotalEarnSpeed().toString(),
                    join.getCampId() == 0 ? "-1" : join.getTotalAbility() + "",
                    join.getCampId() != 0 ? 1 : 0
            ));
        }
    }

    public void lockCamp(List<CrossTonBingUnionJoin> unionJoinList, List<Integer> secondMatchRanges, List<Long> abilityParams) {
        synchronized (lock) {
            if (getCrossTonBingDataMain().isLockUnion()) {
                return;
            }

            // 容错：先清空锁定数据
            for (CrossTonBingUserData userData : userDataMap.values()) {
                if (isAble(userData)) {
                    userData.setCampId(0);
                    userData.setUnionUid("");
                }
            }
            for (CrossTonBingUnionJoin join : unionJoinMap.values()) {
                if (isAble(join)) {
                    join.setCampId(0);
                }
            }

            // 对第1名、第2名、第3名商会进行分配时，直接按照总赚钱进行阵营随机，并且三个商会必然会分在三个阵营中
            int campNum = config.getCampNum();
            int campUnionNum = BigDecimal.valueOf(Math.min(config.getUnionNum(), unionJoinList.size())) // 配置数量和实际数量取最小
                    .divide(BigDecimal.valueOf(config.getCampNum()), 0, BigDecimal.ROUND_UP).intValue();

            List<CampUnion> campUnions = unionJoinList.stream()
                    .map(superClass -> (CampUnion) superClass)
                    .collect(Collectors.toList());

            Camp.divide(campUnions, secondMatchRanges, abilityParams, campNum, campUnionNum, config.getActivityInfo().getActivityId(), 0,
                    eCampActivityType.PEAK_TONGBING);
            // 阵营数据生成
            initCampUserData();
            initGroup();
            initGroupMatchTask();
        }
    }

    /**
     * 锁定阵营
     *
     * @param unionJoinList 参与活动的商会列表
     * @param abilityParams 压缩战力参数
     * @param groupParams   特殊分组参数
     */
    private void newLockCamp(List<CrossTonBingUnionJoin> unionJoinList, List<Long> abilityParams,
                             List<Integer> groupParams) {
        synchronized (lock) {
            if (getCrossTonBingDataMain().isLockUnion()) {
                return;
            }

            // 容错：先清空锁定数据
            for (CrossTonBingUserData userData : userDataMap.values()) {
                if (isAble(userData)) {
                    userData.setCampId(0);
                    userData.setUnionUid("");
                }
            }
            for (CrossTonBingUnionJoin join : unionJoinMap.values()) {
                if (isAble(join)) {
                    join.setCampId(0);
                }
            }

            unionJoinList.sort((o1, o2) -> Long.compare(o2.getTotalAbility(), o1.getTotalAbility()));
            int activityId = config.getActivityInfo().getActivityId();
            for (int i = 0; i < unionJoinList.size(); i++) {
                CrossTonBingUnionJoin unionJoin = unionJoinList.get(i);
                logger.info("活动ID{}--原先按商会总赚钱排名{}--商会UID{}--商会总赚钱{}", activityId, i + 1, unionJoin.getUnionUid(), unionJoin.getTotalAbility());
            }

            // 对所有商会进行战力压缩
            long p0 = abilityParams.get(0);
            long p1 = abilityParams.get(1);
            long p2 = abilityParams.get(2);
            long p3 = abilityParams.get(3);
            if (p0 <= 5 && p1 <= 2 && p2 <= 5 && p3 <= 5) {
                for (CrossTonBingUnionJoin union : unionJoinList) {
                    BigDecimal totalAbility = new BigDecimal(union.getTotalAbility() < 0 ? 0 :
                            union.getTotalAbility()); // 商会总赚钱，别让根号下的数字为负数
                    BigDecimal memberNum = new BigDecimal(union.getMemberMap().size()); // 商会总人数
                    // 利用公式对总赚钱进行战力压缩
                    // x = p0√totalAbility * memberNum
                    // y = (x^p1) / p2 - p3 * x
                    try {
                        BigDecimal x = BigDecimal.valueOf(Math.pow(totalAbility.doubleValue(),
                                1.0 / abilityParams.get(0))).multiply(memberNum);
                        BigDecimal y = BigDecimal.valueOf(Math.pow(x.doubleValue(), abilityParams.get(1)))
                                .divide(BigDecimal.valueOf(abilityParams.get(2)), 8, RoundingMode.HALF_UP)
                                .subtract(BigDecimal.valueOf(abilityParams.get(3)).multiply(x));
                        union.setCompressedAbility(y);
                    } catch (Exception ex) {
                        logger.error("UUID{} 总战力{} 总人数{} 战力压缩错误!", union.getUnionUid(), totalAbility, memberNum);
                        logger.error("p0{} p1{} p2{} p3{}, 分组参数", p0, p1, p2, p3);
                        union.setCompressedAbility(BigDecimal.valueOf(Integer.MIN_VALUE));
                    }
                }
            } else if (p0 > 5 && p1 > 2 && p2 > 5 && p3 >= 5) {
                for (CrossTonBingUnionJoin union : unionJoinList) {
                    long totalAbility = union.getTotalAbility(); // 商会总赚钱
                    int memberNum = union.getMemberMap().size(); // 商会总人数
                    try {
                        // 利用公式对总赚钱进行战力压缩  v = log(p2)(totalAbility / p0 * p1) * p3 * memberNum;
                        BigDecimal tmp = BigDecimal.valueOf(totalAbility).divide(BigDecimal.valueOf(abilityParams.get(0))
                                , 9, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(abilityParams.get(1)));
                        BigDecimal tmp1 =
                                BigDecimal.valueOf(Math.log(tmp.doubleValue())).divide(BigDecimal.valueOf(Math.log(abilityParams.get(2))), 9,
                                        RoundingMode.HALF_UP);
                        union.setCompressedAbility(tmp1.multiply(BigDecimal.valueOf(abilityParams.get(3))).multiply(BigDecimal
                                .valueOf(memberNum)));
                    } catch (Exception ex) {
                        logger.error("UUID{} 总战力{} 总人数{} 战力压缩错误!", union.getUnionUid(), totalAbility, memberNum);
                        logger.error("p0{} p1{} p2{} p3{}, 分组参数!", p0, p1, p2, p3);
                        union.setCompressedAbility(BigDecimal.valueOf(Integer.MIN_VALUE));
                    }
                }
            }

            // 按压缩战力重新排序
            unionJoinList.sort((o1, o2) -> {
                if (o1.getCompressedAbility().compareTo(o2.getCompressedAbility()) == 0) { // 压缩战力一致，比较总赚钱
                    return Long.compare(o2.getTotalAbility(), o1.getTotalAbility());
                }
                return o2.getCompressedAbility().compareTo(o1.getCompressedAbility());
            });

            for (int i = 0; i < unionJoinList.size(); i++) {
                CrossTonBingUnionJoin unionJoin = unionJoinList.get(i);
                logger.info("活动ID{}--按压缩战力排名{}--商会UID{}--商会压缩战力{}--商会总赚钱{}", activityId, i + 1, unionJoin.getUnionUid(),
                        unionJoin.getCompressedAbility(),
                        unionJoin.getTotalAbility());
            }

            int unionCnt = unionJoinList.size(); // 商会总数
            int campNum = config.getCampNum(); // 阵营总数
            // 将压缩后总赚钱前三名的商会分别分配至不同阵营（魏蜀吴）
            // 在保证有 campNum 个以上的商会参加则为1-campNum，否则取最小值
            // 优先弹出最小压缩战力
            PriorityBlockingQueue<com.yanqu.road.server.manager.activity.tonbing.activity.Camp> camps =
                    new PriorityBlockingQueue<>(campNum, Comparator.comparing(com.yanqu.road.server.manager.activity.tonbing.activity.Camp::getCampAbility));
            for (int idx = 0; idx < Math.min(campNum, unionCnt); idx++) {
                CrossTonBingUnionJoin union = unionJoinList.get(idx);
                List<String> tmp = new ArrayList<>();
                tmp.add(union.getUnionUid());
                com.yanqu.road.server.manager.activity.tonbing.activity.Camp camp = new com.yanqu.road.server.manager.activity.tonbing.activity.Camp(idx + 1, tmp);
                camp.setCampAbility(union.getCompressedAbility());
                camps.add(camp);
                // 修改商会信息
                union.setCampId(idx + 1);
                for (CrossTonBingUnionJoinMember member : union.getMemberMap().values()) {
                    CrossTonBingUserData userData = getUserData(member.getUserId());
                    userData.setCampId(union.getCampId());
                    userData.setUnionUid(union.getUnionUid());
                }
            }

            // 随机排序的范围，在保证有15个以上的商会参加则为4-15，否则取最小值
            int right = Math.min(groupParams.get(1), unionCnt);
            List<CrossTonBingUnionJoin> shuffled = new ArrayList<>();
            for (int idx = groupParams.get(0) - 1; idx < right; idx++) {
                shuffled.add(unionJoinList.get(idx));
            }
            Collections.shuffle(shuffled); // 乱序

            for (int i = 0; i < shuffled.size(); i++) {
                CrossTonBingUnionJoin unionJoin = shuffled.get(i);
                logger.info("活动ID{}--乱序后{}--商会UID{}--商会压缩战力{}--商会总赚钱{}", activityId, i + 1, unionJoin.getUnionUid(),
                        unionJoin.getCompressedAbility(),
                        unionJoin.getTotalAbility());
            }

            // 分组，并按组总压缩战力排序
            List<List<CrossTonBingUnionJoin>> groups = new ArrayList<>();
            int idx1 = 0;
            while (idx1 < shuffled.size()) {
                List<CrossTonBingUnionJoin> sub = new ArrayList<>();
                while (idx1 < shuffled.size() && sub.size() < campNum) {
                    sub.add(shuffled.get(idx1++));
                }
                groups.add(sub);
            }
            groups.sort(Comparator.comparingDouble(o -> o.stream().mapToDouble(CrossTonBingUnionJoin::getCompressedAbilityDouble).sum()));

            for (int i = 0; i < groups.size(); i++) {
                List<CrossTonBingUnionJoin> sub = groups.get(i);
                logger.info("活动ID{}--乱序后{}--分组总战力{}", activityId, i + 1,
                        sub.stream().mapToDouble(CrossTonBingUnionJoin::getCompressedAbilityDouble).sum());
            }

            // 优先弹出最大压缩战力
            PriorityBlockingQueue<CrossTonBingUnionJoin> group =
                    new PriorityBlockingQueue<>(campNum, (o1, o2) -> {
                        if (o2.getCompressedAbility().compareTo(o1.getCompressedAbility()) == 0) { // 压缩战力一致，比较总赚钱
                            return Long.compare(o2.getTotalAbility(), o1.getTotalAbility());
                        }
                        return o2.getCompressedAbility().compareTo(o1.getCompressedAbility());
                    });

            int idx2 = 1;
            for (List<CrossTonBingUnionJoin> sub : groups) {
                group.addAll(sub);
                // 填充到阵营中
                Set<com.yanqu.road.server.manager.activity.tonbing.activity.Camp> set = new HashSet<>(); // 存放弹出的阵营
                logger.info("活动ID{}--{} 分组填充", activityId, idx2++);
                while (!camps.isEmpty() && !group.isEmpty()) {
                    com.yanqu.road.server.manager.activity.tonbing.activity.Camp camp = camps.poll();
                    set.add(camp);
                    CrossTonBingUnionJoin union = group.poll();
                    if (union == null) {
                        continue;
                    }
                    logger.info("活动ID{}--阵营{}--总压缩战力{}", activityId, camp.getCampId(),
                            camp.getCampAbility());
                    logger.info("活动ID{}--商会UID{}--商会压缩战力{}--商会总赚钱{}--加入阵营{}", activityId, union.getUnionUid(),
                            union.getCompressedAbility(),
                            union.getTotalAbility(), camp.getCampId());
                    camp.setCampAbility(camp.getCampAbility().add(union.getCompressedAbility()));
                    camp.getUnions().add(union.getUnionUid());
                    // 修改商会信息
                    union.setCampId(camp.getCampId());
                    for (CrossTonBingUnionJoinMember member : union.getMemberMap().values()) {
                        CrossTonBingUserData userData = getUserData(member.getUserId());
                        userData.setCampId(union.getCampId());
                        userData.setUnionUid(union.getUnionUid());
                    }
                }
                camps.addAll(set);
            }

            // 用于日志记录
            PriorityBlockingQueue<com.yanqu.road.server.manager.activity.tonbing.activity.Camp> tmpCamps =
                    new PriorityBlockingQueue<>(campNum, Comparator.comparing(com.yanqu.road.server.manager.activity.tonbing.activity.Camp::getCampAbility));

            // 剩余商会分配
            int campUnionNum = BigDecimal.valueOf(Math.min(config.getUnionNum(), unionCnt)) // 配置数量和实际数量取最小
                    .divide(BigDecimal.valueOf(config.getCampNum()), 0, BigDecimal.ROUND_UP).intValue();
            for (int idx = right; idx < unionCnt; idx++) {
                CrossTonBingUnionJoin union = unionJoinList.get(idx);
                if (!camps.isEmpty()) {
                    com.yanqu.road.server.manager.activity.tonbing.activity.Camp camp = camps.poll();
                    camp.setCampAbility(camp.getCampAbility().add(union.getCompressedAbility()));
                    camp.getUnions().add(union.getUnionUid());
                    if (camp.getUnions().size() < campUnionNum) { // 超出阵营可容纳商会数则直接将阵营弹出
                        camps.add(camp);
                    }
                    if (camp.getUnions().size() >= campUnionNum) {
                        tmpCamps.add(camp);
                    }
                    // 修改商会信息
                    union.setCampId(camp.getCampId());
                    for (CrossTonBingUnionJoinMember member : union.getMemberMap().values()) {
                        CrossTonBingUserData userData = getUserData(member.getUserId());
                        userData.setCampId(union.getCampId());
                        userData.setUnionUid(union.getUnionUid());
                    }
                }
            }
            logger.info("活动ID{}--阵营商会未满", activityId);
            while (!camps.isEmpty()) {
                com.yanqu.road.server.manager.activity.tonbing.activity.Camp camp = camps.poll();
                logger.info("活动ID{}--阵营{}--压缩战力{}", activityId, camp.getCampId(), camp.getCampAbility());
                for (int i = 0; i < camp.getUnions().size(); i++) {
                    String unionId = camp.getUnions().get(i);
                    for (CrossTonBingUnionJoin union : unionJoinList) {
                        if (union.getUnionUid().equals(unionId)) {
                            logger.info("活动ID{}--序号{}--第{}阵营--商会UID{}--商会压缩战力{}", activityId, i + 1, camp.getCampId(),
                                    union.getUnionUid(), union.getCompressedAbility());
                        }
                    }
                }
            }

            logger.info("活动ID{}--阵营商会已满", activityId);
            while (!tmpCamps.isEmpty()) {
                com.yanqu.road.server.manager.activity.tonbing.activity.Camp camp = tmpCamps.poll();
                logger.info("活动ID{}--阵营{}--压缩战力{}", activityId, camp.getCampId(), camp.getCampAbility());
                for (int i = 0; i < camp.getUnions().size(); i++) {
                    String unionId = camp.getUnions().get(i);
                    for (CrossTonBingUnionJoin union : unionJoinList) {
                        if (union.getUnionUid().equals(unionId)) {
                            logger.info("活动ID{}--序号{}--第{}阵营--商会UID{}--商会压缩战力{}", activityId, i + 1, camp.getCampId(),
                                    union.getUnionUid(), union.getCompressedAbility());
                        }
                    }
                }
            }
            // 阵营数据生成
            initCampUserData();
            initGroup();
            initGroupMatchTask();
        }
    }

    /**
     * 原先的阵营分配逻辑
     *
     * @param unionJoinList 参与活动的商会列表
     */
    private void lockCamp(List<CrossTonBingUnionJoin> unionJoinList) {
        synchronized (lock) {
            if (getCrossTonBingDataMain().isLockUnion()) {
                return;
            }

            // 容错：先清空锁定数据
            for (CrossTonBingUserData userData : userDataMap.values()) {
                if (isAble(userData)) {
                    userData.setCampId(0);
                    userData.setUnionUid("");
                }
            }
            for (CrossTonBingUnionJoin join : unionJoinMap.values()) {
                if (isAble(join)) {
                    join.setCampId(0);
                }
            }

            // 按门客赚钱重新排序
            unionJoinList = unionJoinList.stream().sorted(new Comparator<CrossTonBingUnionJoin>() {
                @Override
                public int compare(CrossTonBingUnionJoin o1, CrossTonBingUnionJoin o2) {
                    return Long.compare(o2.getTotalAbility(), o1.getTotalAbility());
                }
            }).collect(Collectors.toList());

            Map<Integer, Long> campAbilityMap = new ConcurrentHashMap<>();
            Map<Integer, List<String>> campUnionMap = new ConcurrentHashMap<>();

            int campNum = config.getCampNum();
            int campUnionNum = BigDecimal.valueOf(Math.min(config.getUnionNum(), unionJoinList.size())) // 配置数量和实际数量取最小
                    .divide(BigDecimal.valueOf(config.getCampNum()), 0, BigDecimal.ROUND_UP).intValue();
            for (int i = 1; i <= campNum; i++) {
                campAbilityMap.put(i, 0L);
                campUnionMap.put(i, new ArrayList<>());
            }

            // 遍历商会一个个分配
            for (CrossTonBingUnionJoin join : unionJoinList) {
                int minCamp = 1;
                long minAbility = Long.MAX_VALUE;
                for (Map.Entry<Integer, Long> entry : campAbilityMap.entrySet()) {
                    // 跳过已经分配满的阵营
                    if (campUnionMap.get(entry.getKey()).size() >= campUnionNum) {
                        continue;
                    }
                    // 取总赚钱最小的阵营（赚钱相同时，随机一下，避免一直一样）
                    if (entry.getValue() < minAbility ||
                            entry.getValue() == minAbility && randomHelper.next(2) == 0) {
                        minCamp = entry.getKey();
                        minAbility = entry.getValue();
                    }
                }

                long sum = join.getTotalAbility();
                campAbilityMap.put(minCamp, campAbilityMap.get(minCamp) + sum);
                campUnionMap.get(minCamp).add(join.getUnionUid());

                // 修改数据
                join.setCampId(minCamp);
                for (CrossTonBingUnionJoinMember member : join.getMemberMap().values()) {
                    CrossTonBingUserData userData = getUserData(member.getUserId());
                    userData.setCampId(join.getCampId());
                    userData.setUnionUid(join.getUnionUid());
                }
            }

            // 阵营数据生成
            initCampUserData();
            initGroup();
            initGroupMatchTask();
        }
    }

    //先随便分组初始的第一场分
    private void initGroup(){
        List<Integer> warTypeList = config.getWarTypeList();
        Map<Integer,Map<Integer,Map<Integer,List<String>>>> turnMap = new ConcurrentHashMap<>();
        //第一轮
        turnMap.put(1,new ConcurrentHashMap<>());
        //战场1
        turnMap.get(1).put(warTypeList.get(0),new ConcurrentHashMap<>());
        for(CrossTonBingUnionJoin join : unionJoinMap.values()){
            if(!turnMap.get(1).get(warTypeList.get(0)).containsKey(join.getCampId())){
                turnMap.get(1).get(warTypeList.get(0)).put(join.getCampId(),new ArrayList<>());
            }
            turnMap.get(1).get(warTypeList.get(0)).get(join.getCampId()).add(join.getUnionUid());
        }
        crossTonBingDataMain.setTurnUnionMap(turnMap);
        crossTonBingDataMain.setWinnerMap(new ConcurrentHashMap<>());
    }

    //第二天了结束掉前一天的比赛，开始进行晋级
    private void checkGameOver(){
        int matchMaxTurn = 0;
        for(int turn : turnMatchMap.keySet()){
            if(matchMaxTurn < turn){
                matchMaxTurn = turn;
            }
        }
        Map<Integer,Map<Integer,List<String>>> upMap = new ConcurrentHashMap<>();
        int nowConfigTurn = config.getTurn();
        if(nowConfigTurn == 0){
            return;
        }
        int upTurn = nowConfigTurn;
        if(matchMaxTurn + 1 < nowConfigTurn){
            upTurn = matchMaxTurn + 1;
        }
        int lastTurn = upTurn - 1;
        //没有当前的分组，结束上一轮开始生成
        if(!turnMatchMap.containsKey(upTurn)){
            if(turnMatchMap.containsKey(lastTurn)){
                for(int warType : turnMatchMap.get(lastTurn).keySet()){
                    for(CrossTonBingMatch match : turnMatchMap.get(lastTurn).get(warType).values()){
                        if(!match.isGameOver()){
                            match.setGameOver(true);
                            match.setStop(true);
                            Map<Integer,Map<Integer,List<String>>> riseMap = riseMatchUnion(match);
                            for(int riseWarType : riseMap.keySet()){
                                if(!upMap.containsKey(riseWarType)){
                                    upMap.put(riseWarType,new ConcurrentHashMap<>());
                                }
                                for(int riseCampId : riseMap.get(riseWarType).keySet()){
                                    if(!upMap.get(riseWarType).containsKey(riseCampId)) {
                                        upMap.get(riseWarType).put(riseCampId,new ArrayList<>());
                                    }
                                    upMap.get(riseWarType).get(riseCampId).addAll(riseMap.get(riseWarType).get(riseCampId));
                                }
                            }
                        }
                    }
                }
                Map<Integer, Map<Integer, Map<Integer, List<String>>>> turnMap = crossTonBingDataMain.getTurnUnionMap();
                if(!turnMap.containsKey(upTurn)){
                    turnMap.put(upTurn,new ConcurrentHashMap<>());
                }
                turnMap.get(upTurn).putAll(upMap);
                crossTonBingDataMain.setTurnUnionMap(turnMap);
                logger.error("晋级完成{}轮次",upTurn);
                initAllRankList();
            }
        }
    }

    //晋级商会，没晋级的原地保留 战场 阵营
    private Map<Integer,Map<Integer,List<String>>> riseMatchUnion(CrossTonBingMatch match){
        int turn = match.getCrossTonBingData().getTurn();
        int wayType = match.getCrossTonBingData().getWarType();
        int riseNum = config.getGroupRuleList(turn);
        Map<Integer,Map<Integer,List<String>>> resMap = new ConcurrentHashMap<>();
        Map<String, CrossTonBingUnionJoin> unionMap = match.getUnionJoinMap();
        Map<Integer,List<CrossTonBingRank>> campUnionMap = new ConcurrentHashMap<>();
        resMap.put(wayType,new ConcurrentHashMap<>());
        resMap.put(wayType + 1,new ConcurrentHashMap<>());
        Map<Integer, CrossTonBingRankListModel> matchCampUnionRankMap = match.getCampUnionRankMap();
        for(int campId : matchCampUnionRankMap.keySet()){
            if(!campUnionMap.containsKey(campId)){
                campUnionMap.put(campId,new ArrayList<>());
            }
            CrossTonBingRankListModel model = matchCampUnionRankMap.get(campId);
            for(CrossTonBingRank rank : model.getRankList()){
                campUnionMap.get(campId).add(rank);
            }
        }
        /*for(CrossTonBingUnionJoin join : unionMap.values()){
            CrossTonBingRise riseData = new CrossTonBingRise();
            riseData.setUnionId(join.getUnionUid());
            riseData.setZhangong(getUnionZhangong(join));
            if(!campUnionMap.containsKey(join.getCampId())){
                campUnionMap.put(join.getCampId(),new ArrayList<>());
            }
            campUnionMap.get(join.getCampId()).add(riseData);
        }*/
        for(int campId : campUnionMap.keySet()){
            List<CrossTonBingRank> riseList = campUnionMap.get(campId);
            riseList.sort(new CrossTonBingRankSort());
            int index = 0;
            for(CrossTonBingRank riseData : riseList){
                if(index < riseNum){
                    if(!resMap.get(wayType + 1).containsKey(campId)){
                        resMap.get(wayType + 1).put(campId,new ArrayList<>());
                    }
                    resMap.get(wayType + 1).get(campId).add(riseData.getId());
                }else{
                    if(!resMap.get(wayType).containsKey(campId)){
                        resMap.get(wayType).put(campId,new ArrayList<>());
                    }
                    resMap.get(wayType).get(campId).add(riseData.getId());
                }
                index++;
            }
        }
        for(int warType : resMap.keySet()){
            if(resMap.get(warType).size() == 0){
                resMap.remove(warType);
            }
        }
        return resMap;
    }

    class UnionZhangongSort implements Comparator<CrossTonBingRise> {
        @Override
        public int compare(CrossTonBingRise o1, CrossTonBingRise o2) {
            if (o1.getZhangong() == o2.getZhangong()) {
                return 0;
            }
            if (o1.getZhangong() > o2.getZhangong()) {
                return -1;
            }
            return 1;
        }
    }


    private long getUnionZhangong(CrossTonBingUnionJoin unionJoin){
        long myValue = 0;
        for (CrossTonBingUnionJoinMember member : unionJoin.getMemberMap().values()) {
            CrossTonBingUserData tmp = getUserData(member.getUserId());
            myValue += tmp.getZhanGong();
        }
        return myValue;
    }

    public void initGroupMatchTask(){
        long next5Second = System.currentTimeMillis() + DateHelper.SECOND_MILLIONS + 5000;
        addTask(new CrossTonBingMakeMatchTask(this, next5Second));
        //榜单还没锁定不用这里操作
        if(crossTonBingDataMain.isLockUnion()){
            //每一组最大多少人
            synchronized (lock){
                int turn = config.getTurn();
                if(turn != 0){
                    checkGameOver();
                    //要是中间开始前面的也要生成
                    for(int i = 1; i <= turn;i++){
                        if(!crossTonBingDataMain.getTurnUnionMap().containsKey(i)){
                            continue;
                        }
                        if(turnMatchMap.containsKey(i)){
                            continue;
                        }
                        makeGroupMatch(i);
                    }
                }
            }
        }
    }

    class GroupRankSort implements Comparator<CrossTonBingRank> {
        @Override
        public int compare(CrossTonBingRank o1, CrossTonBingRank o2) {
            return Long.compare(o2.getValue(), o1.getValue());
        }
    }

    private void makeGroupMatch_back(int turn){
        Map<Integer,Integer> campIdRankMap = new ConcurrentHashMap<>();
        //第一轮没有上一轮的排名,用来报错阵营排名产出辎重的buff
        if(turn != 1){
            List<CrossTonBingRank> rankList = new ArrayList<>();
            Map<Integer,Integer> campIdIntMap = new ConcurrentHashMap<>();
            Map<Integer,Map<Integer,Map<Integer,Long>>> mmMap = getCampValueMap();
            for(Map<Integer,Map<Integer,Long>> dataMap : mmMap.values()){
                Map<Integer,Long> intMap = dataMap.get(2);//积分
                for(int cId : intMap.keySet()){
                    campIdIntMap.put(cId,campIdIntMap.getOrDefault(cId,0));
                }
            }
            if(campIdIntMap.size() > 0){
                for(int campId : campIdIntMap.keySet()){
                    CrossTonBingRank rank = new CrossTonBingRank();
                    rank.setId(campId + "");
                    rank.setValue(campIdIntMap.get(campId));
                    rankList.add(rank);
                }
                rankList.sort(new GroupRankSort());
                int rank = 1;
                for(CrossTonBingRank rankInfo : rankList){
                    campIdRankMap.put(Integer.valueOf(rankInfo.getId()),rank);
                    rank++;
                }
            }
        }

        int unionMax = config.getUnionMax();
        Map<Integer, Map<Integer, Map<Integer, List<String>>>> turnMap = crossTonBingDataMain.getTurnUnionMap();
        if(!turnMap.containsKey(turn)){
            return;
        }
        Map<Integer, Map<Integer, List<String>>> warTypeMap = turnMap.get(turn);
        for(int warType : warTypeMap.keySet()){
            Map<Integer, List<String>> campUnionIdMap = new ConcurrentHashMap<>();
            for(int campId : warTypeMap.get(warType).keySet()){
                campUnionIdMap.put(campId,new ArrayList<>(warTypeMap.get(warType).get(campId)));
            }
            //当达不到配置数的商会的时候用最大的分组来分，就不会出现有商会被落下了
            int allCount = 0;
            int maxCount = 0;
            for(int campId : campUnionIdMap.keySet()){
                if(campUnionIdMap.get(campId).size() > maxCount){
                    maxCount = campUnionIdMap.get(campId).size();
                }
                allCount += campUnionIdMap.get(campId).size();

            }
            int moreUnionCount = allCount % (unionMax * config.getCampNum());
            int groupCount = allCount / (unionMax * config.getCampNum());
            if(moreUnionCount != 0){
                groupCount = groupCount + 1;
            }
            List<CrossTonBingMatch> matchList = new ArrayList<>();
            //比赛生成然后轮流加人
            for(int i = 0; i < groupCount;i++){
                CrossTonBingMatch match = new CrossTonBingMatch(config,null);
                match.initMatchData(turn,warType,matchId.getAndIncrement());
                matchList.add(match);
            }
            while (campUnionIdMap.size() > 0){
                for(CrossTonBingMatch match : matchList){
                    List<String> unionIdList = new ArrayList<>();
                    for(int campId : campUnionIdMap.keySet()){
                        if(campUnionIdMap.get(campId).size() > 0){
                            unionIdList.add(campUnionIdMap.get(campId).get(0));
                            campUnionIdMap.get(campId).remove(0);
                        }else{
                            campUnionIdMap.remove(campId);
                        }
                    }
                    for(String unionId : unionIdList){
                        match.getUnionJoinMap().put(unionId,unionJoinMap.get(unionId));
                    }
                }
            }
            for(CrossTonBingMatch match : matchList) {
                addTurnMatch(match);
                List<CrossTonBingUserData> userDataList = new ArrayList<>();
                for(CrossTonBingUnionJoin unionJoin : match.getUnionJoinMap().values()){
                    for(long userId : unionJoin.getMemberMap().keySet()){
                        CrossTonBingUserData userData = getUserData(userId);
                        userDataList.add(userData);
                        userMatchMap.put(userData.getUserId(),match);
                    }
                }
                match.initUserData(userDataList);
                match.saveLastRank(campIdRankMap);
                match.initData();
                match.start();
            }
        }
        for(int warType : turnMatchMap.get(turn).keySet()){
            Map<Integer,CrossTonBingMatch> warTypeMatchMap = turnMatchMap.get(turn).get(warType);
            for(CrossTonBingMatch match : warTypeMatchMap.values()){
                for(CrossTonBingUnionJoin join : match.getUnionJoinMap().values()){
                    CrossAutoLogMgr.add(new LogTonBingUnionPeak(
                            config.getActivityInfo().getActivityId(),
                            join.getUnionUid(),
                            turn,
                            join.getCampId(),
                            warType,
                            turn == warType?1:0,
                            match.getCrossTonBingData().getMatchId()
                    ));
                }
            }
        }
        for(CrossTonBingUserData userData : userDataMap.values()){
            syncBaseDataMsg(userData);
        }
    }

    //生成比赛
    private void makeGroupMatch(int turn){
        long startMakeTime = System.currentTimeMillis();
        Map<Integer,Integer> campIdRankMap = new ConcurrentHashMap<>();
        //第一轮没有上一轮的排名,用来报错阵营排名产出辎重的buff
        if(turn != 1){
            LinkedList<CrossTonBingRank> rankList = getCampScoreRankList();
            int rank = 1;
            for(CrossTonBingRank rankInfo : rankList){
                campIdRankMap.put(Integer.valueOf(rankInfo.getId()),rank);
                rank++;
            }
            //不自己写了，用排行榜的吧
            /*List<CrossTonBingRank> rankList = new ArrayList<>();
            Map<Integer,Integer> campIdIntMap = new ConcurrentHashMap<>();
            Map<Integer,Map<Integer,Map<Integer,Long>>> mmMap = getCampValueMap();
            for(Map<Integer,Map<Integer,Long>> dataMap : mmMap.values()){
                Map<Integer,Long> intMap = dataMap.get(2);//积分
                for(int cId : intMap.keySet()){
                    campIdIntMap.put(cId,campIdIntMap.getOrDefault(cId,0));
                }
            }
            if(campIdIntMap.size() > 0){
                for(int campId : campIdIntMap.keySet()){
                    CrossTonBingRank rank = new CrossTonBingRank();
                    rank.setId(campId + "");
                    rank.setValue(campIdIntMap.get(campId));
                    rankList.add(rank);
                }
                rankList.sort(new GroupRankSort());
                int rank = 1;
                for(CrossTonBingRank rankInfo : rankList){
                    campIdRankMap.put(Integer.valueOf(rankInfo.getId()),rank);
                    rank++;
                }
            }*/
        }

        int unionMax = config.getUnionMax();
        Map<Integer, Map<Integer, Map<Integer, List<String>>>> turnMap = crossTonBingDataMain.getTurnUnionMap();
        if(!turnMap.containsKey(turn)){
            return;
        }
        Map<Integer, Map<Integer, List<String>>> warTypeMap = turnMap.get(turn);
        Map<Integer, Map<Integer, Map<String,Long>>> newMap = makeMatchRankUnion(warTypeMap);
        for(int warType : newMap.keySet()){
            Map<Integer, Map<String,Long>> campUnionIdMap = newMap.get(warType);
            //当达不到配置数的商会的时候用最大的分组来分，就不会出现有商会被落下了
            int allCount = 0;
            int maxCount = 0;
            for(int campId : campUnionIdMap.keySet()){
                if(campUnionIdMap.get(campId).size() > maxCount){
                    maxCount = campUnionIdMap.get(campId).size();
                }
                allCount += campUnionIdMap.get(campId).size();

            }
            int moreUnionCount = allCount % (unionMax * config.getCampNum());
            int groupCount = allCount / (unionMax * config.getCampNum());
            if(moreUnionCount != 0){
                groupCount = groupCount + 1;
            }
            //生成每一个租的商会数据
            //组id campId 商会列表
            Map<Integer,Map<Integer,List<String>>> groupMap = new ConcurrentHashMap<>();
            //组id campId 总赚钱
            Map<Integer,Map<Integer,Long>> groupZhuanqianMap = new ConcurrentHashMap<>();
            for(int i = 0; i < groupCount;i++){
                groupMap.put(i + 1,new ConcurrentHashMap<>());
                groupZhuanqianMap.put(i + 1,new ConcurrentHashMap<>());
                for(int cp = 1 ; cp <= config.getCampNum(); cp++){
                    groupMap.get(i + 1).put(cp,new ArrayList<>());
                    groupZhuanqianMap.get(i + 1).put(cp,0L);
                }
            }
            while (campUnionIdMap.size() > 0){
                for(int campId : campUnionIdMap.keySet()){
                    List<CrossTonBingRank> rankList = new ArrayList<>();
                    //商会也要排一下再去生成按顺序从大到小来
                    for(String unionId : campUnionIdMap.get(campId).keySet()){
                        CrossTonBingRank rank = new CrossTonBingRank(unionId,campUnionIdMap.get(campId).get(unionId),0);
                        rankList.add(rank);
                    }
                    rankList.sort(new CrossTonBingRankSort());
                    for(CrossTonBingRank rank : rankList){
                        addUnionToGroup(groupMap,groupZhuanqianMap,campUnionIdMap,rank.getId(),campId);
                    }
                }
            }

            List<CrossTonBingMatch> matchList = new ArrayList<>();
            //比赛生成然后轮流加人
            for(int i = 0; i < groupCount;i++){
                CrossTonBingMatch match = new CrossTonBingMatch(config,null);
                match.initMatchData(turn,warType,matchId.getAndIncrement());
                for(List<String> unionIdList : groupMap.get(i + 1).values()){
                    for(String unionId : unionIdList){
                        match.getUnionJoinMap().put(unionId,unionJoinMap.get(unionId));
                    }
                }
                matchList.add(match);
            }
            for(CrossTonBingMatch match : matchList) {
                addTurnMatch(match);
                List<CrossTonBingUserData> userDataList = new ArrayList<>();
                for(CrossTonBingUnionJoin unionJoin : match.getUnionJoinMap().values()){
                    for(long userId : unionJoin.getMemberMap().keySet()){
                        CrossTonBingUserData userData = getUserData(userId);
                        userDataList.add(userData);
                        userMatchMap.put(userData.getUserId(),match);
                    }
                }
                match.initUserData(userDataList);
                match.saveLastRank(campIdRankMap);
                match.initData();
                match.start();
            }
        }
        for(int warType : turnMatchMap.get(turn).keySet()){
            Map<Integer,CrossTonBingMatch> warTypeMatchMap = turnMatchMap.get(turn).get(warType);
            for(CrossTonBingMatch match : warTypeMatchMap.values()){
                for(CrossTonBingUnionJoin join : match.getUnionJoinMap().values()){
                    CrossAutoLogMgr.add(new LogTonBingUnionPeak(
                            config.getActivityInfo().getActivityId(),
                            join.getUnionUid(),
                            turn,
                            join.getCampId(),
                            warType,
                            turn == warType?1:0,
                            match.getCrossTonBingData().getMatchId()
                    ));
                }
            }
        }
        for(CrossTonBingUserData userData : userDataMap.values()){
            syncBaseDataMsg(userData);
            syncUserDataToGameServer(userData,true);
        }
        long endMakeTime = System.currentTimeMillis();
        logger.info("第{}轮比赛生成花费时间{}毫秒",turn,endMakeTime - startMakeTime);
    }

    //获得当前的战场的最小赚钱的组且没有达到
    private int addUnionToGroup(Map<Integer,Map<Integer,List<String>>> groupMap,
                                Map<Integer,Map<Integer,Long>> groupZhuanqianMap,
                                Map<Integer, Map<String,Long>> campUnionIdMap,
                                String unionId,
                               int campId){
        int unionMax = config.getUnionMax();
        List<CrossTonBingRank> rankList = new ArrayList<>();
        for(Integer groupId : groupZhuanqianMap.keySet()){
            if(groupMap.get(groupId).get(campId).size() >= unionMax){
                continue;
            }
            Map<Integer,Long> campZhuanqianMap = groupZhuanqianMap.get(groupId);
            CrossTonBingRank rank = new CrossTonBingRank(groupId + "",campZhuanqianMap.getOrDefault(campId,0L),0);
            rankList.add(rank);
        }
        rankList.sort(new CrossTonBingRankSort());
        CrossTonBingRank selectRank = rankList.get(rankList.size() - 1);
        groupMap.get(Integer.valueOf(selectRank.getId())).get(campId).add(unionId);
        groupZhuanqianMap.get(Integer.valueOf(selectRank.getId())).put(campId,
                groupZhuanqianMap.get(Integer.valueOf(selectRank.getId())).getOrDefault(campId,0L) +
                        campUnionIdMap.get(campId).get(unionId));
        campUnionIdMap.get(campId).remove(unionId);
        if(campUnionIdMap.get(campId).size() == 0){
            campUnionIdMap.remove(campId);
        }
        return 1;
    }

    //把所有战场和对应阵营的商会排名下
    private Map<Integer, Map<Integer, Map<String,Long>>> makeMatchRankUnion(Map<Integer, Map<Integer, List<String>>> warTypeMap){
        Map<Integer, Map<Integer, Map<String,Long>>> newMap = new ConcurrentHashMap<>();
        for(int warType : warTypeMap.keySet()){
            newMap.put(warType,new ConcurrentHashMap<>());
            Map<Integer, List<String>> campUnionMap = warTypeMap.get(warType);
            for(int campId : campUnionMap.keySet()){
                newMap.get(warType).put(campId,new ConcurrentHashMap<>());
                List<CrossTonBingRank> rankList = new ArrayList<>();
                for(String unionId : campUnionMap.get(campId)){
                    CrossTonBingUnionJoin unionJoin = getUnionJoin(unionId);
                    CrossTonBingRank rank = new CrossTonBingRank(unionId,unionJoin.getTotalAbility(),0);
                    rankList.add(rank);
                }
                rankList.sort(new CrossTonBingRankSort());
                for(CrossTonBingRank rank : rankList){
                    newMap.get(warType).get(campId).put(rank.getId(),rank.getValue());
                }
            }
        }
        return newMap;
    }

    //把对应的比赛加入
    private void addTurnMatch(CrossTonBingMatch match){
        CrossTonBingData data = match.getCrossTonBingData();
        if(!turnMatchMap.containsKey(data.getTurn())){
            turnMatchMap.put(data.getTurn(),new ConcurrentHashMap<>());
        }
        if(!turnMatchMap.get(data.getTurn()).containsKey(data.getWarType())){
            turnMatchMap.get(data.getTurn()).put(data.getWarType(),new ConcurrentHashMap<>());
        }
        turnMatchMap.get(data.getTurn()).get(data.getWarType()).put(data.getMatchId(),match);
        matchMap.put(data.getMatchId(),match);
    }

    /**
     * 初始化阵营数据
     */
    private void initCampUserData() {

        logger.info("initCampUserData activityId {}.", config.getActivityInfo().getActivityId());

        // 阵营数据生成
        for (int campId = 1; campId <= config.getCampNum(); campId++) {
            if (!campDataMap.containsKey(campId)) {
                CrossTonBingCampData campData = new CrossTonBingCampData();
                campData.setActivityId(config.getActivityInfo().getActivityId());
                campData.setCampId(campId);
                campData.setInsertOption();
                campDataMap.put(campId, campData);
            } else {
                // 已有数据说明有问题...
                logger.error("ton bing initCampUserData, repeated create data? activityId {}, campId {}.", config.getActivityInfo().getActivityId(), campId);
                CrossTonBingCampData campData = campDataMap.get(campId);
                campData.setRedPacketMap(new ConcurrentHashMap<>());
                campData.setRedPacketValue(0L);
                campData.setUserRedPacketMap(new ConcurrentHashMap<>());
                campDataMap.put(campId, campData);
            }
        }
    }



    /**
     * 是否有资格
     */
    private boolean isAble(CrossTonBingUserData userData) {
        return userData.getCampId() != 0;
    }

    /**
     * 是否有资格
     */
    private boolean isAble(CrossTonBingUnionJoin join) {
        return join.getCampId() != 0;
    }

    public CrossTonBingMatch getMatchByUserId(long userId) {
        if(!userMatchMap.containsKey(userId)){
            return null;
        }
        return userMatchMap.get(userId);
    }

    public CrossTonBingMatch getMatchByMatchId(int matchId) {
        if(!matchMap.containsKey(matchId)){
            return null;
        }
        return matchMap.get(matchId);
    }
    // ============================== 队伍 ==============================

    /**
     * 更新门客数据（没资格也可以更新，不然游戏第一次进来没有值）
     *
     * @param first               首次同步不用设置CD，队伍士兵补满
     * @param isRefreshMaxSoldier 是否只刷新兵力上限
     */
    private int updatePatronsAbility(CrossTonBingUserData userData, boolean first, Map<Integer, CrossTonBingPatrons> patronsMap, List<Long> addition, boolean isRefreshMaxSoldier) {
        CrossTonBingMatch match = getMatchByUserId(userData.getUserId());
        if(match != null){
            return match.updatePatronsAbility(userData,first,patronsMap,addition,isRefreshMaxSoldier);
        }
        return 0;
    }

    // ============================== CMD ==============================

    public void loginByCmd(long userId, TonBingProto.CrossTonBingLoginReqMsg reqMsg) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        CrossTonBingUserData userData = getUserData(userId);
        // 第一次帮他同步
        if (userData.getPatronsMap().isEmpty() && (match !=null && match.getUserData(userId) != null)) {
            updatePatronsAbility(userData, true, CrossTonBingPb.parseCrossTonBingPatrons(reqMsg.getPatronsListList()), reqMsg.getSoldierAdditionList(), false);
        }
        // 同步数据
        syncBaseDataMsg(userData);
        // 跨服同步用户数据到游戏服
        syncUserDataToGameServer(userData,false);
        //任命了别人别人可能没在线，登录的时候再同步一次
        syncUserPosition(userId);
        // 同步战功成就
        notifyConditionChange(userId, eGamePlayerEventType.TonBingZhanGong, userData.getZhanGong());
        // 同步全部红点
        if (config.inShowActivityTime()) {
            TonBingProto.TonBingSyncRedDotRespMsg.Builder builder = TonBingProto.TonBingSyncRedDotRespMsg.newBuilder();
            builder.addAllType(userData.getRedDotMap().keySet());
            sendPacket(ClientProtocol.U_TON_BING_SYNC_RED_DOT, builder, userData.getUserId());
        }
        // 同步高亮玩家
        syncLight();
        if(match != null){
            // 同步阵营指挥官
            match.syncCommanderInfo(userId, userData.getCampId());
        }
    }

    private TonBingProto.CrossTonBingCityWinerAppointRespMsg.Builder parsePosAppoint(TonBingProto.CrossTonBingCityWinerAppointRespMsg.Builder msg, Map<Integer, Integer> positionMap){
        Map<Integer, Integer> posMap = new ConcurrentHashMap(positionMap);
        for(int type : posMap.keySet()){
            TonBingProto.TonBingPositionMsg.Builder posMsg = TonBingProto.TonBingPositionMsg.newBuilder();
            posMsg.setType(type);
            posMsg.setPositionId(posMap.get(type));
            msg.addPosition(posMsg);
        }
        return msg;
    }

    private TonBingProto.TonBingUserPositionMsg.Builder parsePosUser(TonBingProto.TonBingUserPositionMsg.Builder msg,Map<Integer, Integer> positionMap){
        Map<Integer, Integer> posMap = new ConcurrentHashMap(positionMap);
        for(int type : posMap.keySet()){
            TonBingProto.TonBingPositionMsg.Builder posMsg = TonBingProto.TonBingPositionMsg.newBuilder();
            posMsg.setType(type);
            posMsg.setPositionId(posMap.get(type));
            msg.addPosition(posMsg);
        }
        return msg;
    }

    private void syncUserPosition(long userId) {
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
        if (userBaseInfo != null) {
            CrossTonBingUserData userData = getUserData(userId);
            if (isAble(userData) && userData.getPositionMap().size() != 0) {
                TonBingProto.CrossTonBingCityWinerAppointRespMsg.Builder crespMsg = TonBingProto.CrossTonBingCityWinerAppointRespMsg.newBuilder();
                crespMsg.setWinerName("");
                parsePosAppoint(crespMsg,userData.getPositionMap());
                crespMsg.setCampId(userData.getCampId());
                crespMsg.setSendReward(false);
                MessageHelper.sendPacket(userBaseInfo.getServerId(), userId, YanQuMessageUtils.buildMessage(GameProtocol.S_CROSS_TON_BING_CITY_APPOINT_POSITION, crespMsg));
            }
        }
    }
    //没有自己报名了
    /*public void updateUnionByCmd(TonBingProto.CrossTonBingGetUnionRespMsg reqMsg) {

        List<Long> syncList = new ArrayList<>();

        synchronized (lock) {

            // 时间
            boolean lockUnion = getCrossTonBingDataMain().isLockUnion();
            boolean activityEnd = System.currentTimeMillis() > config.getActivityInfo().getEndTime() * 1000L;

            // 结束了就无法操作了
            if (activityEnd) {
                return;
            }

            // 自动报名数据（这里还是按赚速，拿不到最高赚钱）
            boolean autoJoin = reqMsg.getType() == 2;
            List<TonBingProto.TonBingUnionMsg> rankList = reqMsg.getUnionList().stream().sorted(new Comparator<TonBingProto.TonBingUnionMsg>() {
                @Override
                public int compare(TonBingProto.TonBingUnionMsg o1, TonBingProto.TonBingUnionMsg o2) {
                    BigInteger bigInt1 = new BigInteger(o1.getUnionInfo().getTotalEarnSpeed());
                    BigInteger bigInt2 = new BigInteger(o2.getUnionInfo().getTotalEarnSpeed());
                    return bigInt2.compareTo(bigInt1);
                }
            }).collect(Collectors.toList());

            // 遍历数据一个个处理
            for (TonBingProto.TonBingUnionMsg unionMsg : rankList) {

                // 【商会处理】
                CrossTonBingUnionJoin join = unionJoinMap.get(unionMsg.getUnionUid());
                if (join == null) {
                    // 自动报名 && 未锁名单 && 有空位
                    if (autoJoin && !lockUnion && unionJoinMap.size() < config.getUnionNum()) {
                        join = new CrossTonBingUnionJoin();
                        join.setActivityId(config.getActivityInfo().getActivityId());
                        join.setUnionUid(unionMsg.getUnionUid());
                        join.setUnionBaseInfo(UnionBasePb.parseUnionBaseInfo(unionMsg.getUnionInfo()));
                        join.setMemberMap(new ConcurrentHashMap<>());
                        join.setInsertOption();
                        unionJoinMap.put(join.getUnionUid(), join);
                        // 日志
                        CrossTonBingLog.addLogChannelTonBingJoin(new LogTonBingJoin(
                                config.getActivityInfo().getActivityId(),
                                -1,
                                unionMsg.getUnionUid(),
                                1,
                                unionMsg.get
                        ));
                    }
                }
                if (join == null) {
                    continue;
                }

                // 【成员处理】
                Map<Long, CrossTonBingUnionJoinMember> oldMap = join.getMemberMap();
                if (!lockUnion) {
                    Map<Long, CrossTonBingUnionJoinMember> memberMap = new ConcurrentHashMap<>();
                    for (TonBingProto.TonBingUnionMemberInfoMsg msg : unionMsg.getMemberList()) {
                        CrossTonBingUnionJoinMember member = oldMap.remove(msg.getUserId());
                        if (member == null) {
                            member = new CrossTonBingUnionJoinMember(msg.getUserId(), msg.getServerId());
                            syncList.add(member.getUserId()); // 添加报名状态同步
                        }
                        member.setPosition(msg.getPosition());
                        memberMap.put(member.getUserId(), member);
                    }
                    join.setMemberMap(memberMap);
                    syncList.addAll(oldMap.keySet()); // 添加报名状态同步
                } else {
                    for (TonBingProto.TonBingUnionMemberInfoMsg msg : unionMsg.getMemberList()) {
                        CrossTonBingUnionJoinMember member = oldMap.get(msg.getUserId());
                        if (member != null) {
                            member.setPosition(msg.getPosition());
                        }
                    }
                }
                join.setUpdateOption();
            }
        }

        // 同步报名状态
        for (Long userId : syncList) {
            syncBaseDataMsg(getUserData(userId));
        }

        // 没赚钱的拉一下
        if (!getCrossTonBingDataMain().isLockUnion()) {
            for (TonBingProto.TonBingUnionMsg unionMsg : reqMsg.getUnionList()) {
                checkUnionJoinMember(unionMsg.getUnionUid());
            }
        }

    }*/

    public void updateUnionMemberByCmd(TonBingProto.CrossTonBingGetMemberRespMsg reqMsg) {
        synchronized (lock) {
            if (getCrossTonBingDataMain().isLockUnion()) {
                return;
            }

            for (TonBingProto.TonBingUnionMemberMsg memberMsg : reqMsg.getMemberList()) {
                CrossTonBingUnionJoin join = unionJoinMap.get(memberMsg.getUnionUid());
                if (join == null || !join.getMemberMap().containsKey(memberMsg.getUserId())) {
                    continue;
                }

                CrossTonBingUnionJoinMember member = join.getMemberMap().get(memberMsg.getUserId());
                member.setEarnSpeed(Long.valueOf(memberMsg.getEarnSpeed()));
                if (memberMsg.hasPatronsTopAbility() && Long.valueOf(memberMsg.getPatronsTopAbility()) > member.getTopAbility()) {
                    member.setTopAbility(Long.valueOf(memberMsg.getPatronsTopAbility()));
                    join.reCalcAbility();
                }
                join.setUpdateOption();
            }
        }
    }

    public void notifyUnionMemberChangeByCmd(String unionUid) {
        // 没报名，不管
        CrossTonBingUnionJoin unionJoin = getUnionJoin(unionUid);
        if (unionJoin == null) {
            return;
        }
        // 结束了，不管
        if (System.currentTimeMillis() > config.getActivityInfo().getEndTime() * 1000L) {
            return;
        }
        // 重新拉一下商会成员数据
        sendGetUnionMsg(1, Collections.singletonList(unionUid), 0);
    }

    public void syncPatronsByCmd(TonBingProto.CrossTonBingUpdatePatronsReqMsg reqMsg) {
        CrossTonBingMatch match = getMatchByUserId(reqMsg.getUserId());
        if(match != null){
            match.syncPatronsByCmd(reqMsg);
        }
    }

    public void syncUserPositionSliver() {
        Map<Long, List<CrossTonBingUserData>> needSyncUserDataMap = new ConcurrentHashMap<>(getNeedSyncPosUserDataMap());
        for (Long serverId : needSyncUserDataMap.keySet()) {
            TonBingProto.CrossTonBingPositionSliverSyncMsg.Builder syncMsg = TonBingProto.CrossTonBingPositionSliverSyncMsg.newBuilder();
            List<CrossTonBingUserData> userDataList = needSyncPosUserData.get(serverId);
            for (CrossTonBingUserData userData : userDataList) {
                TonBingProto.CrossTonBingPositionUserMsg.Builder userMsg = TonBingProto.CrossTonBingPositionUserMsg.newBuilder();
                userMsg.setUserId(userData.getUserId());
                Map<Long, BigInteger> addMap = userData.getPosAddSilverMap();
                for (long userId : addMap.keySet()) {
                    UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
                    if (userBaseInfo != null) {
                        TonBingProto.TonBingPositionSliverMsg.Builder sliverUserMsg = TonBingProto.TonBingPositionSliverMsg.newBuilder();
                        sliverUserMsg.setUserId(userId);
                        sliverUserMsg.setSliver(addMap.get(userId).toString());
                        sliverUserMsg.setPlayerBaseData(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
                        userMsg.addSliverUser(sliverUserMsg);
                    }
                }
                syncMsg.addUser(userMsg);
            }
            MessageHelper.sendPacket(serverId, 0, YanQuMessageUtils.buildMessage(GameProtocol.S_CROSS_TON_BING_POS_REWARD_SYNC, syncMsg));
        }
    }


    /**
     * 设置战略目标
     */
    public void setTargetCityByCmd(long userId, TonBingProto.TonBingSetTargetCityReqMsg reqMsg) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.setTargetCityByCmd(userId,reqMsg);
        }
    }

    public void moveTeamByCmd(long userId, TonBingProto.TonBingMoveTeamReqMsg reqMsg) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.moveTeamByCmd(userId,reqMsg);
        }
    }

    public void speedUpByCmd(long userId, TonBingProto.TonBingMoveSpeedUpReqMsg reqMsg) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.speedUpByCmd(userId,reqMsg);
        }
    }
    //检查一下门客有没有，一般是会有的，测试时间调来调去会导活动乱七八糟会导致没有
    private void checkPatrons(long userId){
        CrossTonBingUserData userData = getUserData(userId);
        if(userData.getCampId() != 0){
            if(userData.getPatronsMap().size() == 0){
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
                if(userBaseInfo != null){
                    TonBingProto.TonBingUpdatePatronsAbilityReqMsg.Builder msg = TonBingProto.TonBingUpdatePatronsAbilityReqMsg.newBuilder();
                    MessageHelper.sendPacket(userBaseInfo.getServerId(), userId, YanQuMessageUtils.buildMessage(GameProtocol.S_TON_BING_UPDATE_PATRONS_ABILITY, msg));
                }
            }
        }
    }

    public void getDataByCmd(long userId,int matchId) {
        if(matchId == 0){
            watchMap.remove(userId);
        }
        for(CrossTonBingMatch match : matchMap.values()){
            match.removeWatchPlayer(userId);
        }
        CrossTonBingMatch match = getMatchByMatchId(matchId);
        if(match != null){
            match.getDataByCmd(userId);
            watchMap.put(userId,matchId);
        }
    }

    public void getMyTeamPosByCmd(long userId, TonBingProto.TonBingGetBattlefieldMyTeamReqMsg reqMsg) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.getMyTeamPosByCmd(userId,reqMsg);
        }
    }

    public void getPosReward(long serverId, long userId) {
        TonBingProto.TonBingPosGetRewardRespMsg.Builder respMsg = TonBingProto.TonBingPosGetRewardRespMsg.newBuilder();
        respMsg.setRet(0);
        CrossTonBingUserData userData = getUserData(userId);
        if (!isAble(userData)) {
            respMsg.setRet(GameErrorCode.E_TON_BING_NO_ABLE);
            sendPacket(ClientProtocol.U_TON_BING_GET_POS_REWARD, respMsg, userId);
            return;
        }
        synchronized (lock) {
            if (userData.getPositionMap().size() == 0) {
                respMsg.setRet(GameErrorCode.E_TON_BING_POS_REWARD_CAN_NOT_GET);
                sendPacket(ClientProtocol.U_TON_BING_GET_POS_REWARD, respMsg, userId);
                return;
            }
            Map<Integer,Map<Integer, TonBingTitleConfig>> titleConfigMap = config.getTitleConfigMap();
            Map<Long, BigInteger> rewardMap = userData.getPosAddSilverMap();
            BigInteger allValue = BigInteger.ZERO;
            Map<Integer, Integer> posMap = userData.getPositionMap();
            for(int posType : posMap.keySet()){
                TonBingTitleConfig titleConfig = titleConfigMap.get(posType).get(posMap.get(posType));
                if (titleConfig.getType() != 1) {
                    continue;
                }
                for (long unLuckUserId : rewardMap.keySet()) {
                    BigInteger value = rewardMap.get(unLuckUserId);
                    allValue = allValue.add(value);
                    rewardMap.put(unLuckUserId, BigInteger.ZERO);
                    userData.setUpdateOption();
                }
            }

            if (allValue.compareTo(BigInteger.ZERO) == 0) {
                respMsg.setRet(GameErrorCode.E_TON_BING_NO_POS_REWARD);
                sendPacket(ClientProtocol.U_TON_BING_GET_POS_REWARD, respMsg, userId);
                return;
            }
            userData.setPosAddSilverMap(rewardMap);
            respMsg.setReward(GameConfig.GAME_MONEY_SILVER + "=" + allValue.toString());
        }
        MessageHelper.sendPacket(serverId, userId, YanQuMessageUtils.buildMessage(GameProtocol.S_CROSS_TON_BING_GET_POS_REWARD, respMsg));
    }

    //获得城池战报
    public void cityWarReport(long userId) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.cityWarReport(userId);
        }
    }

    //获得个人战报
    public void userWarReport(long userId) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.userWarReport(userId);
        }
    }

    //城主信息
    public void getCityWinner(long userId) {
//        testSendMaill();
        TonBingProto.TonBingCityWinerRespMsg.Builder respMsg = TonBingProto.TonBingCityWinerRespMsg.newBuilder();
        respMsg.setRet(0);
//        long winnerUserId = crossTonBingData.getProcess2WinUserId();
        Map<Integer, Long> winnerMap = crossTonBingDataMain.getWinnerMap();
        for(int winnerType : winnerMap.keySet()){
            Long winnerId = winnerMap.get(winnerType);
            CrossTonBingUserData winnerData = getUserData(winnerId);
            TonBingProto.TonBingCityWinnerMsg.Builder winnerMsg = TonBingProto.TonBingCityWinnerMsg.newBuilder();
            winnerMsg.setType(winnerType);
            for(CrossTonBingUserData userData : userDataMap.values()){
                Map<Integer, Integer> posMap = userData.getPositionMap();
                //如果是皇帝，可以命名自己阵营的
                if(winnerType == 0){
                    if(userData.getCampId() != winnerData.getCampId()){
                        continue;
                    }
                }else{//如果是城主，可以命名自己商会的
                    if(!userData.getUnionUid().equals(winnerData.getUnionUid())){
                        continue;
                    }
                }
                boolean needSync = posMap.containsKey(winnerType); // 有职位，必须发
                if (userId == winnerId) { // 自己是城主，就要所有人的信息
                    needSync = true;
                }
                if (!needSync) {
                    continue;
                }
                UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userData.getUserId());
                if (userBaseInfo != null) {
                    TonBingProto.TonBingUserPositionMsg.Builder userMsg = TonBingProto.TonBingUserPositionMsg.newBuilder();
                    userMsg.setUserId(userData.getUserId());
                    userMsg.setCampId(userData.getCampId());
                    userMsg.setZhangong(userData.getZhanGong());
                    parsePosUser(userMsg,userData.getPositionMap());
                    /*TonBingProto.TonBingPositionMsg.Builder posMsg = TonBingProto.TonBingPositionMsg.newBuilder();
                    if(posMap.containsKey(winnerType)){
                        posMsg.setType(winnerType);
                        posMsg.setPositionId(posMap.get(winnerType));
                        userMsg.addPosition(posMsg);
                    }*/
                    userMsg.setPlayerBaseData(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
                    userMsg.setTotalPosSilver(userData.getTotalPosSilver().toString());
                    winnerMsg.addList(userMsg);
                }
            }
            respMsg.addList(winnerMsg);
        }
        sendPacket(ClientProtocol.U_TON_BING_CITY_WINNER, respMsg, userId);
    }

    //获取玩家的赚速，任命职位的时候扣别人的赚速加到自己身上就是用这个赚速
    private BigInteger getUserEarnSpeed(long userId) {
        CrossTonBingUserData userData = getUserData(userId);
        if (userData == null) {
            return BigInteger.ZERO;
        }
        if (unionJoinMap.containsKey(userData.getUnionUid())) {
            Map<Long, CrossTonBingUnionJoinMember> joinMemberMap = unionJoinMap.get(userData.getUnionUid()).getMemberMap();
            if (joinMemberMap.containsKey(userId)) {
                return BigInteger.valueOf(joinMemberMap.get(userId).getEarnSpeed());
            }
        }
        return BigInteger.ZERO;
    }

    //任命职位
    public void cityWinnerAppointPosition(long userId, TonBingProto.CrossTonBingCityWinerAppointReqMsg reqMsg) {
        TonBingProto.TonBingCityWinerRespMsg.Builder respMsg = TonBingProto.TonBingCityWinerRespMsg.newBuilder();
        respMsg.setRet(0);
        //吧有洛阳的城池的城主弄过来
        Map<Integer, Long> winnerMap = crossTonBingDataMain.getWinnerMap();
        if (!winnerMap.containsKey(reqMsg.getType()) || winnerMap.get(reqMsg.getType()) != userId) {
            respMsg.setRet(GameErrorCode.E_TON_BING_APPOINT_NOT_WINNER);
            sendPacket(ClientProtocol.U_TON_BING_CITY_WINNER_APPOINT, respMsg, userId);
            return;
        }
        if (reqMsg.getPosition() == eTonBingPosition.Master.getValue()) {
            respMsg.setRet(GameErrorCode.E_TON_BING_APPOINT_NOT_WINNER);
            sendPacket(ClientProtocol.U_TON_BING_CITY_WINNER_APPOINT, respMsg, userId);
            return;
        }
        CrossTonBingUserData winnerUserData = getUserData(userId);
        CrossTonBingUserData userData = getUserData(reqMsg.getUserId());//任命的玩家
        synchronized (lock) {
            Map<Integer,Map<Integer, TonBingTitleConfig>> titleConfigMap = config.getTitleConfigMap();
            if (!titleConfigMap.get(reqMsg.getType()).containsKey(reqMsg.getPosition())) {
                respMsg.setRet(GameErrorCode.E_TON_BING_USER_POSITION_APPOINT_ERR);
                sendPacket(ClientProtocol.U_TON_BING_CITY_WINNER_APPOINT, respMsg, userId);
                return;
            }
            TonBingTitleConfig titleConfig = titleConfigMap.get(reqMsg.getType()).get(reqMsg.getPosition());
            Map<Integer, Integer> posMap = userData.getPositionMap();
//            if (posMap.containsKey(reqMsg.getType()) && posMap.get(reqMsg.getType()) != eTonBingPosition.None.getValue()) {
            if (posMap.size() > 0) {
                respMsg.setRet(GameErrorCode.E_TON_BING_USER_POSITION_APPOINT);
                sendPacket(ClientProtocol.U_TON_BING_CITY_WINNER_APPOINT, respMsg, userId);
                return;
            }
            //任命的时候校验下是不是这个职位已经任命过了
            for(CrossTonBingUserData userDd : new ArrayList<>(userDataMap.values())){
                Map<Integer, Integer> posDdMap = userDd.getPositionMap();
                if(posDdMap.containsKey(reqMsg.getType()) && posDdMap.get(reqMsg.getType()) == reqMsg.getPosition()){
                    respMsg.setRet(GameErrorCode.E_TON_BING_USER_POSITION_APPOINT_ERR);
                    sendPacket(ClientProtocol.U_TON_BING_CITY_WINNER_APPOINT, respMsg, userId);
                    return;
                }
            }
            Map<Integer, Integer> winnerPosMap = winnerUserData.getPositionMap();
            if(!winnerPosMap.containsKey(reqMsg.getType()) || winnerPosMap.get(reqMsg.getType()) != eTonBingPosition.Master.getValue()){
                respMsg.setRet(GameErrorCode.E_TON_BING_USER_APPOINT_ERR_POSITION);
                sendPacket(ClientProtocol.U_TON_BING_CITY_WINNER_APPOINT, respMsg, userId);
                return;
            }
            //皇帝只能任命自己阵营的，城主只能任命自己商会的
            if(reqMsg.getType() == 0){
                if (winnerUserData.getCampId() != userData.getCampId()){
                    respMsg.setRet(GameErrorCode.E_TON_BING_USER_APPOINT_ERR_POSITION);
                    sendPacket(ClientProtocol.U_TON_BING_CITY_WINNER_APPOINT, respMsg, userId);
                    return;
                }
            }else{
                if (!winnerUserData.getUnionUid().equals(userData.getUnionUid())){
                    respMsg.setRet(GameErrorCode.E_TON_BING_USER_APPOINT_ERR_POSITION);
                    sendPacket(ClientProtocol.U_TON_BING_CITY_WINNER_APPOINT, respMsg, userId);
                    return;
                }
            }
            if (winnerUserData.getCampId() == userData.getCampId()) {
                if (titleConfig.getType() != 1) {
                    respMsg.setRet(GameErrorCode.E_TON_BING_USER_APPOINT_ERR_POSITION);
                    sendPacket(ClientProtocol.U_TON_BING_CITY_WINNER_APPOINT, respMsg, userId);
                    return;
                }
            } else {
                if (titleConfig.getType() != 2) {
                    respMsg.setRet(GameErrorCode.E_TON_BING_USER_APPOINT_ERR_POSITION);
                    sendPacket(ClientProtocol.U_TON_BING_CITY_WINNER_APPOINT, respMsg, userId);
                    return;
                }
            }
            posMap.put(reqMsg.getType(),reqMsg.getPosition());
            userData.setPositionMap(posMap);
            Map<Integer,Integer> appointMap = new ConcurrentHashMap<>();
            appointMap.put(reqMsg.getType(),reqMsg.getPosition());

            //任命开始算钱
            userData.setPosAddSilverTime(System.currentTimeMillis());
            if (titleConfig.getType() == 1) {
                addNeedSyncPosUser(userData);
            }

            // 日志
            CrossAutoLogMgr.add(new LogTonBingAppoint(
                    config.getActivityInfo().getActivityId(),
                    userId,
                    reqMsg.getUserId(),
                    titleConfig.getId(),
                    winnerUserData.getCampId()
            ));

            //减益buff还要去本服通知扣除他英两的增加
            UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userData.getUserId());
            UserBaseInfo winnerUserBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
            if (userBaseInfo != null) {
                TonBingProto.CrossTonBingCityWinerAppointRespMsg.Builder crespMsg = TonBingProto.CrossTonBingCityWinerAppointRespMsg.newBuilder();
                crespMsg.setWinerName(winnerUserBaseInfo == null ? "" : winnerUserBaseInfo.getNickName());
                parsePosAppoint(crespMsg,appointMap);
                crespMsg.setCampId(userData.getCampId());
                crespMsg.setSendReward(true);
                MessageHelper.sendPacket(userBaseInfo.getServerId(), userData.getUserId(), YanQuMessageUtils.buildMessage(GameProtocol.S_CROSS_TON_BING_CITY_APPOINT_POSITION, crespMsg));
            } else {
                logger.error("统兵任命找不到任命玩家的userBaseInfo");
            }
            addRedDot(userData,eTonBingRedDotType.Type12_BeAppoint);

            sendPacket(ClientProtocol.U_TON_BING_CITY_WINNER_APPOINT, respMsg, userId);
        }
    }

    /**
     * 任命指挥官
     */
    public void campCommanderAppoint(long userId, TonBingProto.CrossTonBingCampCommanderAppointReqMsg reqMsg) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.campCommanderAppoint(userId,reqMsg);
        }
    }

    /**
     * 指挥官设置信息
     */
    public void commanderSet(long userId, TonBingProto.CrossTonBingCommanderSetReqMsg reqMsg) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.commanderSet(userId,reqMsg);
        }
    }

    /**
     * 获取同阵营的用户数据
     */
    public void getCampUserData(long userId, TonBingProto.CrossTonBingCampUserDataReqMsg reqMsg) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.getCampUserData(userId,reqMsg);
        }
    }

    public void getUserBarracksInfo(long userId) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.getUserBarracksInfo(userId);
        }
    }

    /**
     * 获取招募所需银两
     */
    public void recruitSoldierSliver(long serverId, long userId, TonBingProto.CrossTonBingRecruitSoldierReqMsg reqMsg) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.recruitSoldierSliver(serverId,userId,reqMsg);
        }
    }

    /**
     * 招募士兵
     */
    public void recruitSoldier(long serverId, long userId, TonBingProto.CrossTonBingRecruitSoldierReqMsg reqMsg) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.recruitSoldier(serverId,userId,reqMsg);
        }
    }

    public void changeSoldier(long userId, TonBingProto.CrossTonBingChangeTeamSoldierReqMsg reqMsg) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.changeSoldier(userId,reqMsg);
        }
    }

    public void makeNpcEvent() {
        for(CrossTonBingMatch match : matchMap.values()){
            if(!match.isGameOver()){
                match.makeNpcEvent();
            }
        }
    }

    //处理事件
    public void dealEvent(long userId, TonBingProto.CrossTonBingDealEventReqMsg reqMsg) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.dealEvent(userId,reqMsg);
        }
    }

    public void getBattleFieldByCmd(long userId, TonBingProto.TonBingGetBattlefieldReqMsg reqMsg) {
        if(watchMap.containsKey(userId)){
            CrossTonBingMatch match = getMatchByMatchId(watchMap.get(userId));
            if(match != null){
                match.getBattleFieldByCmd(userId,reqMsg);
            }
        }
    }

    public void getCityDetailByCmd(long userId, TonBingProto.TonBingGetCityDetailReqMsg reqMsg) {
        if(watchMap.containsKey(userId)){
            CrossTonBingMatch match = getMatchByMatchId(watchMap.get(userId));
            if(match != null){
                match.getCityDetailByCmd(userId,reqMsg);
            }
        }
    }

    public void cityFoodInfo(long userId) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.cityFoodInfo(userId);
        }
    }

    public void cityFoodCollect(long userId) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.cityFoodCollect(userId);
        }
    }


    public void getCityTeamByCmd(long userId, TonBingProto.TonBingSyncCityTeamReqMsg reqMsg) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.getCityTeamByCmd(userId, reqMsg);
        }
    }

    public void useWarDrumByCmd(long userId, TonBingProto.CrossTonBingUseWarDrumReqMsg reqMsg) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.useWarDrumByCmd(userId,reqMsg);
        }
    }

    public void needHelpByCmd(long userId, TonBingProto.TonBingNeedHelpReqMsg reqMsg) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.needHelpByCmd(userId,reqMsg);
        }
    }

    public void getBattlefieldRankByCmd(long userId, TonBingProto.TonBingGetBattlefieldRankReqMsg reqMsg) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.getBattlefieldRankByCmd(userId,reqMsg);
        }
    }

    public void sendChatByCmd(long userId, CrossActivityProto.CrossActivityChatReqMsg.Builder reqMsg) {
        int range = 0;
        int id = 0;
        if (eMessageType.TonBingPublicChat.getValue() == reqMsg.getMsg().getType()) {
            range = CrossTonBingChatLogic.RANGE_ALL;
            id = config.getActivityInfo().getActivityId();
            // 公屏聊天加上阵营
            WorldMessageProto.WorldMessageTempMsg.Builder message = reqMsg.getMsg().toBuilder();
            message.setExtraParams(String.valueOf(getUserData(userId).getCampId()));
            String userAreaParam = getUserAreaParam(message.getUserId());
            if (userAreaParam != null) {//公屏聊天加上赛区
                message.setAreaParam(userAreaParam);
            }
            reqMsg.setMsg(message);
        } else if (eMessageType.TonBingCampChat.getValue() == reqMsg.getMsg().getType()) {
            /**/
            int matchId = watchMap.getOrDefault(userId,0);
            CrossTonBingMatch match = getMatchByMatchId(matchId);
            if(match != null){
                match.sendChatByCmd(userId,reqMsg);
                return;
            }else{
                range = CrossTonBingChatLogic.RANGE_CAMP;
                id = getUserData(userId).getCampId();
            }
        } else if (eMessageType.TonBingBattlefieldChat.getValue() == reqMsg.getMsg().getType()) {
            /*range = CrossTonBingChatLogic.RANGE_SYSTEM;
            UserScene userScene = CrossSceneMgr.getUserScene(userId);
            if (userScene != null && eSceneType.TonBingBattlefield.getValue() == userScene.getSceneType()) {
                try {
                    String cityIdStr = userScene.getSceneId().split("-")[0];
                    id = Integer.valueOf(cityIdStr);
                } catch (Exception e) {
                }
            }*/
            int matchId = watchMap.getOrDefault(userId,0);
            CrossTonBingMatch match = getMatchByMatchId(matchId);
            if(match != null){
                match.sendChatByCmd(userId,reqMsg);
            }
            return;
        }

        if (range <= 0 || id <= 0) {
            return;
        }

        chatLogic.chat(range, id, 1, reqMsg.getMsg(),0);
    }

    public void getChatByCmd(long userId, List<Integer> paramList, int param2) {
        List<WorldMessageProto.WorldMessageTempMsg> dataList = new ArrayList<>();
        if (paramList.isEmpty()) {
            return;
        }
        for (int range : paramList) {
            int id = 0;
            //这个里面有活动的所有人都能看的聊天已经战场公告，战场公告是要去对应比赛拿的这里不用continue
            if (range == CrossTonBingChatLogic.RANGE_ALL) {
                int matchId = watchMap.getOrDefault(userId,0);
                CrossTonBingMatch match = getMatchByMatchId(matchId);
                if(match != null){
                    List<WorldMessageProto.WorldMessageTempMsg> adddataList = match.getChatByCmd(getUserData(userId),range,param2);
                    dataList.addAll(adddataList);
                }
                id = config.getActivityInfo().getActivityId();
            } else if (range == CrossTonBingChatLogic.RANGE_CAMP) {
                id = getUserData(userId).getCampId();
                int matchId = watchMap.getOrDefault(userId,0);
                CrossTonBingMatch match = getMatchByMatchId(matchId);
                if(match != null){
                    List<WorldMessageProto.WorldMessageTempMsg> adddataList = match.getChatByCmd(getUserData(userId),range,param2);
                    dataList.addAll(adddataList);
                    //不用再加下面的了，下面的有不是比赛的阵营聊天
                    continue;
                }
            } else if (range == CrossTonBingChatLogic.RANGE_BATTLEFIELD) {
                // 城池id
                id = param2;
                int matchId = watchMap.getOrDefault(userId,0);
                CrossTonBingMatch match = getMatchByMatchId(matchId);
                if(match != null){
                    List<WorldMessageProto.WorldMessageTempMsg> adddataList = match.getChatByCmd(getUserData(userId),range,param2);
                    dataList.addAll(adddataList);
                }
            }

            if (range <= 0 || id <= 0) {
                continue;
            }
            dataList.addAll(chatLogic.getChatMsg(range, id));
        }

        CrossActivityProto.CrossActivityChatListRespMsg.Builder respMsg = CrossActivityProto.CrossActivityChatListRespMsg.newBuilder();
        respMsg.setActivityId(config.getActivityInfo().getActivityId());
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
        if (userBaseInfo != null) {

            if (dataList.size() > 0) {
                dataList.sort(Comparator.comparingLong(WorldMessageProto.WorldMessageTempMsg::getSendTime));
                WorldMessageProto.WorldMessageListMsg.Builder worldMessageListMsg = WorldMessageProto.WorldMessageListMsg.newBuilder();
                worldMessageListMsg.addAllDataList(dataList);
                respMsg.setDataList(worldMessageListMsg);
            }
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.U_CROSS_ACTIVITY_CHAT_LIST, respMsg);
            MessageHelper.sendPacket(userBaseInfo.getServerId(), userId, pbMsg);
        }
    }

    public void getRankRewardByCmd(long userId, TonBingProto.TonBingGetRankRewardReqMsg reqMsg) {
        int ret = getRankReward(userId, reqMsg.getConditionType());
        if (ret != 0) {
            TonBingProto.TonBingGetRankRewardRespMsg.Builder builder = TonBingProto.TonBingGetRankRewardRespMsg.newBuilder();
            builder.setRet(ret);
            sendPacket(ClientProtocol.U_TON_BING_GET_RANK_REWARD, builder, userId);
        }
    }

    //获取战功和积分的总排名
    private Map<Integer,Map<Integer,Map<Integer,Long>>> getCampValueMap(){
        //matchId 1战功 2积分 campId 值
        Map<Integer,Map<Integer,Map<Integer,Long>>> mmMap = new ConcurrentHashMap<>();
        for(CrossTonBingMatch match : matchMap.values()){
            int matchId = match.getCrossTonBingData().getMatchId();
            mmMap.put(matchId,new ConcurrentHashMap<>());
            Map<Integer, Long> campIntegralMap = new ConcurrentHashMap<>();
            for (CrossTonBingCity city : match.getCrossTonBingData().getCityMap().values()) {
                int campId = city.getCampId();
                int cityId = city.getCityId();
                if (campId == 0) {
                    continue;
                }
                long addIntegral = config.getCityScore(match.getCrossTonBingData().getWarType(),cityId,match.getCrossTonBingData().getTurn());
                long oldIntegral = campIntegralMap.getOrDefault(campId, 0L);
                campIntegralMap.put(campId, oldIntegral + addIntegral);
            }
            mmMap.get(matchId).put(2,campIntegralMap);
            Map<Integer, Long> campZhanGongMap = new ConcurrentHashMap<>();
            for(CrossTonBingUserData userData : match.getUserDataMap().values()){
                Map<Integer, Long> zgMap = userData.getZhanGongMap();
                long addZhangong = zgMap.getOrDefault(matchId,0L);
                long oldZhangong = campZhanGongMap.getOrDefault(userData.getCampId(), 0L);
                campZhanGongMap.put(userData.getCampId(), oldZhangong + addZhangong);
            }
            mmMap.get(matchId).put(1,campZhanGongMap);
        }
        return mmMap;
    }

    //每个比赛战功排名
    private Map<Integer,Map<String,Integer>> getMatchUnionZGRank(){
        Map<Integer,Map<String,Integer>> mUnionZgMap = new ConcurrentHashMap<>();
        for(CrossTonBingMatch match : matchMap.values()){
            Map<String, Integer> unionZhanGongRankMap = new ConcurrentHashMap<>();
            LinkedList<CrossTonBingRank> unionRankList = match.getAllUnionRankMap();
            int rank = 0;
            for(CrossTonBingRank rankData : unionRankList){
                rank++;
                unionZhanGongRankMap.put(rankData.getId(),rank);
            }
            mUnionZgMap.put(match.getCrossTonBingData().getMatchId(),unionZhanGongRankMap);
        }
        return mUnionZgMap;
    }

    //每一场中的每一个商会的战功是多少
    private Map<Integer,Map<String,Long>> getUnionZhangongValueMap(){
        //matchId unionId 战功值
        Map<Integer,Map<String,Long>> mmMap = new ConcurrentHashMap<>();
        for(CrossTonBingMatch match : matchMap.values()){
            int matchId = match.getCrossTonBingData().getMatchId();
            Map<String, Long> unionZhanGongMap = new ConcurrentHashMap<>();
            for(CrossTonBingUserData userData : match.getUserDataMap().values()){
                Map<Integer, Long> zgMap = userData.getZhanGongMap();
                long addZhangong = zgMap.getOrDefault(matchId,0L);
                long oldZhangong = unionZhanGongMap.getOrDefault(userData.getUnionUid(), 0L);
                unionZhanGongMap.put(userData.getUnionUid(), oldZhangong + addZhangong);
            }
            mmMap.put(matchId,unionZhanGongMap);
        }
        return mmMap;
    }

    //每一场比赛的每个阵营的战功排行
    private Map<Integer,Map<Integer,Integer>> getUnionZhangongRankMap(){
        //matchId unionId 战功值
        Map<Integer,Map<Integer,Integer>> resMap = new ConcurrentHashMap<>();
        Map<Integer,Map<Integer,Map<Integer,Long>>> mmMap = getCampValueMap();
        for(int matchId : mmMap.keySet()){
            List<CrossTonBingRank> rankList = new ArrayList<>();
            Map<Integer,Long> campIdZhangongMap = new ConcurrentHashMap<>();
            Map<Integer,Long> intMap = mmMap.get(matchId).get(1);//战功
            for(int cId : intMap.keySet()){
                campIdZhangongMap.put(cId,intMap.getOrDefault(cId,0L));
            }
            if(campIdZhangongMap.size() > 0){
                for(int campId : campIdZhangongMap.keySet()){
                    CrossTonBingRank rank = new CrossTonBingRank();
                    rank.setId(campId + "");
                    rank.setValue(campIdZhangongMap.get(campId));
                    rankList.add(rank);
                }
                Map<Integer, Integer> unionZhanGongRankMap = new ConcurrentHashMap<>();
                rankList.sort(new GroupRankSort());
                int rank = 1;
                for(CrossTonBingRank rankInfo : rankList){
                    unionZhanGongRankMap.put(Integer.valueOf(rankInfo.getId()),rank);
                    rank++;
                }
                resMap.put(matchId,unionZhanGongRankMap);
            }
        }
        return resMap;
    }

    public void getCampRankListByCmd(long userId) {
        TonBingProto.TonBingGetCampRankRespMsg.Builder builder = TonBingProto.TonBingGetCampRankRespMsg.newBuilder();
        builder.setRet(0);
        Map<Integer,Map<Integer,Map<Integer,Long>>> mmMap = getCampValueMap();
        //不知道阵营排行榜是所有的还是对应每一个战场
        for (CrossTonBingRank rank : getCampScoreRankList()) {
            TonBingProto.TonBingCampRankMsg.Builder rankMsg = parseTonBingCampRankMsg(rank);
            int campId = rankMsg.getCampId();
            for(int matchId : mmMap.keySet()){
                CrossTonBingMatch match = matchMap.get(matchId);
                Map<Integer,Map<Integer,Long>> ccMap = mmMap.get(matchId);
                Map<Integer,Long> zgMap = ccMap.get(1);
                Map<Integer,Long> intMap = ccMap.get(2);
                TonBingProto.TonBingCampUnionMatchRankMsg.Builder matchRankMsg = TonBingProto.TonBingCampUnionMatchRankMsg.newBuilder();
                matchRankMsg.setTurn(match.getCrossTonBingData().getTurn());
                matchRankMsg.setMatchId(match.getCrossTonBingData().getMatchId());
                matchRankMsg.setWarType(match.getCrossTonBingData().getWarType());
                matchRankMsg.setIntegral(intMap.getOrDefault(campId,0L));
                matchRankMsg.setZhangong(zgMap.getOrDefault(campId,0L));
                rankMsg.addMatchInfo(matchRankMsg);
            }
            builder.addRank(rankMsg);
        }

        sendPacket(ClientProtocol.U_TON_BING_GET_CAMP_RANK_LIST, builder, userId);
    }

    private TonBingProto.TonBingCampUnionMatchRankMsg.Builder parseTonBingCampUnionMatchRankMsg(CrossTonBingMatch match,Map<Integer,Map<Integer,Long>> ccMap){
        Map<Integer,Long> zgMap = ccMap.get(1);
        Map<Integer,Long> intMap = ccMap.get(2);
        TonBingProto.TonBingCampUnionMatchRankMsg.Builder matchRankMsg = TonBingProto.TonBingCampUnionMatchRankMsg.newBuilder();
        matchRankMsg.setTurn(match.getCrossTonBingData().getTurn());
        matchRankMsg.setMatchId(match.getCrossTonBingData().getMatchId());
        matchRankMsg.setWarType(match.getCrossTonBingData().getWarType());
//        matchRankMsg.setIntegral(intMap.getOrDefault(campId,0L));
//        matchRankMsg.setZhangong(zgMap.getOrDefault(campId,0L));
        return matchRankMsg;
    }

    public void getMatchCampUnionRankListByCmd(long userId, TonBingProto.TonBingGetCampUnionRankReqMsg reqMsg) {
        if(reqMsg.getMatchId() == 0){
            getCampUnionRankListByCmd(userId,reqMsg);
        }else{
            CrossTonBingMatch match = getMatchByMatchId(reqMsg.getMatchId());
            if(match != null){
                match.getCampUnionRankListByCmd(userId,reqMsg);
            }
        }
    }

    //获取当前商会的战场
    private int getNowWarType(String unionId){
        int nowTurn = config.getTurn();
        if(System.currentTimeMillis() > config.getActivityInfo().getEndTime() * 1000){
            nowTurn = config.getLastTurn();
        }
        if(turnMatchMap.containsKey(nowTurn)){
            for(Map<Integer,CrossTonBingMatch> matchMap : new ConcurrentHashMap<>(turnMatchMap.get(nowTurn)).values()){
                for(CrossTonBingMatch match : matchMap.values()){
                    if(match.getUnionJoin(unionId) != null){
                        return match.getCrossTonBingData().getWarType();
                    }
                }
            }
        }
        return 0;
    }

    public void getCampUnionRankListByCmd(long userId, TonBingProto.TonBingGetCampUnionRankReqMsg reqMsg) {
        int campId = reqMsg.getCampId();
        CrossTonBingUserData userData = getUserData(userId);
        String unionUid = userData.getUnionUid();

        TonBingProto.TonBingGetCampUnionRankRespMsg.Builder builder = TonBingProto.TonBingGetCampUnionRankRespMsg.newBuilder();
        builder.setRet(0);
        List<CrossTonBingRank> rankList = new ArrayList<>();
        if (campId == 0) {
            // 获取全部商会
            for (CrossTonBingRankListModel model : campUnionRankMap.values()) {
                if (model != null) {
                    rankList.addAll(model.getRankList());
                }
            }
        } else {
            CrossTonBingRankListModel model = campUnionRankMap.get(campId);
            if (model != null) {
                rankList.addAll(model.getRankList());
            }
        }
        for(CrossTonBingRank rank : rankList){
            CrossTonBingUnionJoin unionJoin = getUnionJoin(rank.getId());
            rank.setWarType(getNowWarType(rank.getId()));
            rank.setAbility(unionJoin.getTotalAbility());
        }
        rankList.sort(new CrossTonBingRankSort());

        int rankShowLimit = unionMaxRankConfig;
        if (campId == 0) {
            rankShowLimit = unionMaxRankConfig * config.getCampNum();
        }
        // 获取商会排名
        int num = 0;
        Map<Integer,Map<String,Long>> mmMap = getUnionZhangongValueMap();
        Map<Integer,Map<Integer,Integer>> rankMap = getUnionZhangongRankMap();
        Map<Integer,Map<String,Integer>> unionZgRankMap = getMatchUnionZGRank();
        for (CrossTonBingRank rank : rankList) {
            num++;
            if (num > rankShowLimit) {
                break;
            }
            builder.addRank(parseTonBingCampUnionRankMsg(rank, getNowWarType(rank.getId()), mmMap, rankMap,unionZgRankMap));
        }

        // 获取商会阵营排名
        int myRank = -1;
        int myCampId = userData.getCampId();
        if (myCampId != 0) {
            CrossTonBingRankListModel model = campUnionRankMap.get(myCampId);
            if (model != null) {
                int cnt = 0;
                for (CrossTonBingRank rank : model.getRankList()) {
                    cnt++;
                    if (cnt > rankShowLimit) {
                        break;
                    }
                    if (Objects.equals(rank.getId(), unionUid)) {
                        myRank = cnt;
                    }
                }
            }
        }
        builder.setMyRank(myRank);

        long myValue = 0L;
        CrossTonBingUnionJoin unionJoin = getUnionJoin(unionUid);
        if (unionJoin != null) {
            for (CrossTonBingUnionJoinMember member : unionJoin.getMemberMap().values()) {
                CrossTonBingUserData tmp = getUserData(member.getUserId());
                myValue += tmp.getZhanGong();
            }
        }
        builder.setMyValue(myValue);




        sendPacket(ClientProtocol.U_TON_BING_GET_CAMP_UNION_RANK_LIST, builder, userId);
    }

    public void getUserRankListByCmd(long userId, TonBingProto.TonBingGetUserRankReqMsg reqMsg) {
        int type = reqMsg.getType();

        long myValue = getUserData(userId).getZhanGong();
        String myId = String.valueOf(userId);
        LinkedList<CrossTonBingRank> rankList;
        int maxRank = 100;

        // 【查其他玩家排名】
        if (type == 3) {
            getOtherUserRankByCmd(userId, reqMsg.getParam());
            return; // ！！！
        }

        if (type == 1) {
            // 【个人榜】
            rankList = userRank.getRankList();
            maxRank = userMaxRankConfig;
        } else if (type == 2) {
            // 【商会内个人榜】
            String unionUid = reqMsg.getParam();
            CrossTonBingUnionJoin unionJoin = getUnionJoin(unionUid);
            if (StringUtils.isNullOrEmpty(unionUid) || unionJoin == null) {
                return; // 参数错误
            }
            // 组装个榜单
            CrossTonBingRankListModel tmpModel = new CrossTonBingRankListModel();
            LinkedList<CrossTonBingRank> tmpList = new LinkedList<>();
            for (Long memberId : unionJoin.getMemberMap().keySet()) {
                CrossTonBingUserData member = getUserData(memberId);
                tmpList.add(new CrossTonBingRank(String.valueOf(member.getUserId()), member.getZhanGong(), member.getZhanGongTime()));
            }
            tmpModel.setRankList(tmpList); // 排序
            rankList = tmpModel.getRankList();
        } else if (type == 4) {
            // 【商会内个人今天榜】
            String unionUid = reqMsg.getParam();
            CrossTonBingUnionJoin unionJoin = getUnionJoin(unionUid);
            if (StringUtils.isNullOrEmpty(unionUid) || unionJoin == null) {
                return; // 参数错误
            }
            // 组装个榜单
            CrossTonBingRankListModel tmpModel = new CrossTonBingRankListModel();
            LinkedList<CrossTonBingRank> tmpList = new LinkedList<>();
            for (Long memberId : unionJoin.getMemberMap().keySet()) {
                CrossTonBingUserData member = getUserData(memberId);
                tmpList.add(new CrossTonBingRank(String.valueOf(member.getUserId()), member.getZhanGong(), member.getZhanGongTime()));
            }
            tmpModel.setRankList(tmpList); // 排序
            rankList = tmpModel.getRankList();
        }  else {
            return; // 参数错误
        }

        TonBingProto.TonBingGetUserRankRespMsg.Builder builder = TonBingProto.TonBingGetUserRankRespMsg.newBuilder();
        builder.setRet(0);

        int myRank = -1;
        int rankNum = 0;
        int beginRank = 0;
        int endRank = 0;
        if (type == 1 && reqMsg.hasPageNo()) {
            beginRank = Math.max(reqMsg.getPageNo() * reqMsg.getPageSize() + 1, 1);
            endRank = Math.min(beginRank + reqMsg.getPageSize() - 1, maxRank);
        }

        for (CrossTonBingRank rank : rankList) {
            rankNum++;
            if (rankNum > maxRank) {
                break;
            }
            if (Objects.equals(rank.getId(), myId)) {
                myRank = rankNum;
            }

            if (type == 1 && reqMsg.hasPageNo()) {
                if (rankNum >= beginRank && rankNum <= endRank) {
                    builder.addRank(parseTonBingUserRankMsg(rank));
                }
            } else {
                builder.addRank(parseTonBingUserRankMsg(rank));
            }
        }

        builder.setMyRank(myRank);
        builder.setMyValue(myValue);
        if (reqMsg.hasPageNo() && reqMsg.hasPageSize()) {
            builder.setPageNo(reqMsg.getPageNo());
            builder.setPageSize(reqMsg.getPageSize());
        }

        sendPacket(ClientProtocol.U_TON_BING_GET_USER_RANK_LIST, builder, userId);
    }

    public void getOtherUserRankByCmd(long userId, String otherUserId) {
        int otherRank = -1;
        long otherValue = 0L;

        int num = 0;
        for (CrossTonBingRank rank : userRank.getRankList()) {
            num++;
            if (num > userMaxRankConfig) {
                break;
            }
            if (Objects.equals(rank.getId(), otherUserId)) {
                otherRank = num;
                otherValue = rank.getValue();
                break;
            }
        }

        TonBingProto.TonBingGetUserRankRespMsg.Builder builder = TonBingProto.TonBingGetUserRankRespMsg.newBuilder();
        builder.setRet(0);
        builder.setMyRank(otherRank);
        builder.setMyValue(otherValue);
        // builder.setRank(); // 传排名，不需要传rankList
        sendPacket(ClientProtocol.U_TON_BING_GET_USER_RANK_LIST, builder, userId);
    }

    public void readRedDotByCmd(long userId, TonBingProto.TonBingReadRedDotReqMsg reqMsg) {
        CrossTonBingUserData userData = getUserData(userId);
        if (isAble(userData)) {
            userData.getRedDotMap().remove(reqMsg.getType());
            userData.setUpdateOption();
        }
    }

    //+++pb+++//
    public TonBingProto.TonBingCampRankMsg.Builder parseTonBingCampRankMsg(CrossTonBingRank rank) {
        Integer campId = Integer.valueOf(rank.getId());

        // 拿一下阵营第一的昵称
        UserBaseInfo userBaseInfo = getCampMaxZhanGongUserBaseInfo(campId);
        String nickname = userBaseInfo == null ? "" : userBaseInfo.getNickName();

        TonBingProto.TonBingCampRankMsg.Builder builder = TonBingProto.TonBingCampRankMsg.newBuilder();
        builder.setCampId(campId);
        builder.setValue(rank.getValue());
        builder.setMaxNickname(nickname);
        return builder;
    }

    //用matchId获得是第几轮的什么战场的第几组
    private int getMatchIdTurn(int matchId){
        CrossTonBingMatch match = getMatchByMatchId(matchId);
        if(match == null){
            return 0;
        }
        Map<Integer,Map<Integer,CrossTonBingMatch>> warTypeMap = turnMatchMap.get(match.getCrossTonBingData().getTurn());
        if(warTypeMap == null){
            return 0;
        }
        Map<Integer,CrossTonBingMatch> matchMap = warTypeMap.get(match.getCrossTonBingData().getWarType());
        if(matchMap == null){
            return 0;
        }
        List<Integer> matchIdList = new ArrayList<>(matchMap.keySet());
        Collections.sort(matchIdList);
        return matchIdList.indexOf(matchId) + 1;
    }

    public TonBingProto.TonBingCampUnionRankMsg.Builder parseTonBingCampUnionRankMsg(CrossTonBingRank rank,int warType,Map<Integer,Map<String,Long>> mmMap,Map<Integer,Map<Integer,Integer>> rankMap, Map<Integer,Map<String,Integer>> unionZgRankMap) {
        String unionUid = rank.getId();
        CrossTonBingUnionJoin crossTonBingUnionJoin = unionJoinMap.get(unionUid);
        UnionBaseInfo unionBaseInfo = crossTonBingUnionJoin == null ? new UnionBaseInfo() : crossTonBingUnionJoin.getUnionBaseInfo();
        TonBingProto.TonBingCampUnionRankMsg.Builder builder = TonBingProto.TonBingCampUnionRankMsg.newBuilder();
        builder.setUnionUid(unionUid);
        builder.setValue(rank.getValue());
        builder.setUnionInfo(UnionBasePb.parseUnionBaseTempMsg(unionBaseInfo));
        builder.setCampId(crossTonBingUnionJoin == null ? 0 : crossTonBingUnionJoin.getCampId());
        CrossTonBingUnionJoin join = getUnionJoin(unionUid);
        for(int matchId : mmMap.keySet()){
            CrossTonBingMatch match = matchMap.get(matchId);
            //判断这场比赛是不是有这个商会
            CrossTonBingUnionJoin matchJoin = match.getUnionJoin(unionUid);
            if(matchJoin == null)continue;
            if(!config.isRankStartTime(match.getCrossTonBingData().getTurn())){
                continue;
            }
            Map<String,Long> ccMap = mmMap.get(matchId);
            TonBingProto.TonBingCampUnionMatchRankMsg.Builder matchRankMsg = TonBingProto.TonBingCampUnionMatchRankMsg.newBuilder();
            matchRankMsg.setTurn(match.getCrossTonBingData().getTurn());
            matchRankMsg.setMatchId(getMatchIdTurn(match.getCrossTonBingData().getMatchId()));
            matchRankMsg.setWarType(match.getCrossTonBingData().getWarType());
            matchRankMsg.setIntegral(0);
            matchRankMsg.setZhangong(ccMap.getOrDefault(join.getUnionUid(),0L));
//            matchRankMsg.setUnionZhangongRank(rankMap.get(matchId).getOrDefault(join.getCampId(),0));
            matchRankMsg.setUnionZhangongRank(unionZgRankMap.get(matchId).getOrDefault(join.getUnionUid(),0));
            builder.addMatchInfo(matchRankMsg);
        }
        builder.setWarType(warType);

        return builder;
    }
    public TonBingProto.TonBingUserRankMsg.Builder parseTonBingUserRankMsg(CrossTonBingRank rank) {
        Long userId = Long.valueOf(rank.getId());
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(userId);
        if (userBaseInfo == null) {
            userBaseInfo = new UserBaseInfo();
        }
        CrossTonBingUserData userData = getUserData(userId);
        int campId = userData.getCampId();

        TonBingProto.TonBingUserRankMsg.Builder builder = TonBingProto.TonBingUserRankMsg.newBuilder();
        builder.setUserId(userId);
        builder.setPlayerBaseData(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
        builder.setValue(rank.getValue());
        builder.setCampId(campId);
        for(int matchId : userData.getZhanGongMap().keySet()){
            CrossTonBingMatch match = getMatchByMatchId(matchId);
            if(match != null){
                if(!config.isRankStartTime(match.getCrossTonBingData().getTurn())){
                    continue;
                }
                TonBingProto.TonBingUserMatchInfoMsg.Builder matchInfoMsg = TonBingProto.TonBingUserMatchInfoMsg.newBuilder();
                matchInfoMsg.setWarType(match.getCrossTonBingData().getWarType());
                matchInfoMsg.setTurn(match.getCrossTonBingData().getTurn());
                matchInfoMsg.setZhangong(userData.getZhanGongMap().get(matchId));
                builder.addMatchInfo(matchInfoMsg);
            }
        }

        return builder;
    }
    public TonBingProto.TonBingRedPacketMsg.Builder parseTonBingRedPacketMsg(CrossTonBingRedPacket redPacket, boolean getReward) {
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(redPacket.getUserId());
        if (userBaseInfo == null) {
            userBaseInfo = new UserBaseInfo();
        }

        TonBingProto.TonBingRedPacketMsg.Builder tempMsg = TonBingProto.TonBingRedPacketMsg.newBuilder();
        tempMsg.setUserId(redPacket.getUserId());
        tempMsg.setNickName(userBaseInfo.getNickName());
        tempMsg.setUnionName(userBaseInfo.getUnionName());
        tempMsg.setType(redPacket.getGoodId());
        tempMsg.setOrderNo("" + redPacket.getRedPacketNo());
        tempMsg.setIsGet(getReward ? 1 : 0);
        return tempMsg;
    }

    // ============================== SYNC ==============================

    public void syncBaseDataMsg(CrossTonBingUserData userData) {
        if (userData == null) {
            return;
        }

        int joinStatus = 0; // 0未报名、1已报名、2有资格、3商会未入选
        if (getCrossTonBingDataMain().isLockUnion()) {
            joinStatus = isAble(userData) ? 2 : 3;
        } else {
            for (CrossTonBingUnionJoin join : unionJoinMap.values()) {
                if (join.getMemberMap().containsKey(userData.getUserId())) {
                    joinStatus = 1;
                    break;
                }
            }
        }

        TonBingProto.TonBingSyncBaseDataRespMsg.Builder builder = TonBingProto.TonBingSyncBaseDataRespMsg.newBuilder();
        builder.setJoinStatus(joinStatus);
        if (userData.getCampId() != 0) {
            builder.setCampId(userData.getCampId());
        }
        builder.setSyncPatronsTime(userData.getLastSyncPatronsTime());
        builder.setGuide(userData.getGuide());
        builder.setSyncNeedHelpTime(userData.getNeedHelpTime());
        sendPacket(ClientProtocol.U_TON_BING_SYNC_BASE_DATA, builder, userData.getUserId());
    }

    /**
     * 跨服同步用户数据到游戏服
     */
    public void syncUserDataToGameServer(CrossTonBingUserData userData,boolean sendPatrons) {
        if (userData == null) {
            return;
        }
        TonBingProto.CrossTonBingSyncUserDataMsg.Builder builder = TonBingProto.CrossTonBingSyncUserDataMsg.newBuilder();
        builder.setCampId(userData.getCampId());
        builder.setZhanGong(userData.getZhanGong());
        builder.setSendLogin(sendPatrons);
        sendPacket(GameProtocol.S_CROSS_TON_BING_SYNC_USER_DATA, builder, userData.getUserId());
    }

    /**
     * 同步发光数据
     */
    private void syncLight() {
        List<Long> userIdList = new ArrayList<>();
        for (CrossTonBingRank rank : userRank.getRankList()) {
            if (userIdList.size() >= config.getLightRankNum() || rank.getValue() < config.getLightNeedZhanGong()) {
                break;
            }
            userIdList.add(Long.valueOf(rank.getId()));
        }

        // 获取在活动内的玩家
        long now = System.currentTimeMillis();
        List<Long> recUsers = userDataMap.values().stream().filter(item -> isInActivity(item, now)).map(CrossTonBingUserData::getUserId).collect(Collectors.toList());
        if (recUsers.isEmpty()) {
            return;
        }

        TonBingProto.TonBingSyncLightUserRespMsg.Builder builder = TonBingProto.TonBingSyncLightUserRespMsg.newBuilder();
        builder.addAllUserId(userIdList);
        sendPacketToAll(ClientProtocol.U_TON_BING_SYNC_LIGHT_USER, builder, recUsers);
    }


    // ============================== 聊天 ==============================
    public void syncChat(int range, int id, WorldMessageProto.WorldMessageTempMsg chatMsg,int matchId) {
        long now = System.currentTimeMillis();
        List<Long> userIdList = new ArrayList<>();
        if (range == CrossTonBingChatLogic.RANGE_ALL) {
            if(matchId != 0){
                CrossTonBingMatch match = getMatchByMatchId(matchId);
                if(match != null){
                    match.syncChat(range,id,chatMsg,matchId);
                }
                return;
            }
            // 所有人都要接收，所以换个发包方式
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.A_WORLD_MESSAGE_TRANSFER, chatMsg);
            for (long serverId : config.getActivityInfo().getServerIdList()) {
                MessageHelper.sendPacket(serverId, 0, pbMsg);
            }
            return;
        } else if (range == CrossTonBingChatLogic.RANGE_CAMP) {
            if(matchId != 0){
                CrossTonBingMatch match = getMatchByMatchId(matchId);
                if(match != null){
                    match.syncChat(range,id,chatMsg,matchId);
                }
                return;
            }else{
                //外部的阵营聊天变成外部的独立，只同步不在战场的囧
                List<Long> syncUserIdList = new ArrayList<>();
                for(CrossTonBingUserData userData : userDataMap.values()){
                    if(userData.getCampId() == id){
                        syncUserIdList.add(userData.getUserId());
                    }
                }
                syncUserIdList.removeAll(watchMap.keySet());
                sendPacketToAll(ClientProtocol.U_WORLD_MESSAGE_SYNC, chatMsg.toBuilder(), syncUserIdList);
                return;
//                userIdList = userDataMap.values().stream().filter(item -> item.getCampId() == id && isInActivity(item, now)).mapToLong(item -> item.getUserId()).boxed().collect(Collectors.toList());
            }
        } else if (range == CrossTonBingChatLogic.RANGE_BATTLEFIELD) {
//            CrossTonBingMatch match = getMatchByUserId(chatMsg.getUserId());
            CrossTonBingMatch match = getMatchByMatchId(matchId);

            if(match != null){
                CrossTonBingBattlefield battlefield = match.getCrossTonBingData().getCityMap().get(id).getBattlefield();
                if (battlefield != null) {
                    for (Integer partId : battlefield.getPartMap().keySet()) {
                        List<Long> list = CrossSceneMgr.getSceneUserList(config.getActivityInfo().getActivityId(),
                                eSceneType.TonBingBattlefield.getValue(),
                                match.getCrossTonBingData().getMatchId() + "-" + getBattlefieldSceneKey(id, partId),
                                23333)
                                .stream().mapToLong(item -> item.getUserId()).boxed().collect(Collectors.toList());
                        userIdList.addAll(list);
                    }
                }
            }
        }
        if (!userIdList.isEmpty()) {
            sendPacketToAll(ClientProtocol.U_WORLD_MESSAGE_SYNC, chatMsg.toBuilder(), userIdList);
        }
    }

    // ============================== 其他 ==============================

    public void save() {
        for(CrossTonBingMatch match : matchMap.values()){
            match.save();
        }

        if (crossTonBingDataMain.isInsertOption()) {
            TonBingActivityBusiness.addCrossTonBingDataMain(crossTonBingDataMain);
        } else if (crossTonBingDataMain.isUpdateOption()) {
            TonBingActivityBusiness.updateCrossTonBingDataMain(crossTonBingDataMain);
        }

        for (CrossTonBingUnionJoin join : unionJoinMap.values()) {
            if (join.isInsertOption()) {
                TonBingActivityBusiness.addCrossTonBingUnionJoin(join);
            } else if (join.isUpdateOption()) {
                TonBingActivityBusiness.updateCrossTonBingUnionJoin(join);
            }
        }

        for (CrossTonBingUserData data : userDataMap.values()) {
            if (data.isInsertOption()) {
                TonBingActivityBusiness.addCrossTonBingUserData(data);
            } else if (data.isUpdateOption()) {
                TonBingActivityBusiness.updateCrossTonBingUserData(data);
            }
        }

        for (CrossTonBingCampData campData : campDataMap.values()) {
            if (campData.isInsertOption()) {
                TonBingActivityBusiness.addCrossTonBingCampData(campData);
            } else if (campData.isUpdateOption()) {
                TonBingActivityBusiness.updateCrossTonBingCampData(campData);
            }
        }
    }

    /**
     * 玩家是否在界面内
     */
    public boolean isInActivity(CrossTonBingUserData data, long now) {
        if (!isAble(data)) {
            return false; // 无资格的都进不了界面
        }
        if (now - data.getLastReqTime() < DateHelper.MINUTE_MILLIONS * 3) {
            return true; // 3分钟内有请求的都当他在线
        }
        return false;
    }

    /**
     * 设置请求时间
     */
    public void setLastReqTime(long userId) {
        if (userId <= 0) {
            return;
        }
        CrossTonBingUserData userData = getUserData(userId);
        userData.setLastReqTime(System.currentTimeMillis());
    }

    public void printTask() {
        Map<String, Integer> countMap = new ConcurrentHashMap<>();
        for (BaseCrossTonBingActivityTask task : taskQueue) {
            countMap.put(task.getType().name(), countMap.getOrDefault(task.getType().name(), 0) + 1);
        }
        for(CrossTonBingMatch match : matchMap.values()){
            if(!match.isGameOver()){
                match.printTask();
            }
        }

        logger.info("【统兵演武任务】 - {}", JSON.toJSONString(countMap));
    }

    public String getBattlefieldSceneKey(int cityId, int partId) {
        return cityId + "-" + partId;
    }

    public String getTeamKey(CrossTonBingTeam team) {
        return team.getUserId() + "-" + team.getOccupation();
    }

    public String getTeamKey(CrossTonBingTeamArrive arrive) {
        return arrive.getUserId() + "-" + arrive.getTeamId();
    }

    public CrossTonBingTeam getTeamByKey(String key) {
        String[] split = key.split("-");
        CrossTonBingUserData userData = getUserData(Long.valueOf(split[0]));
        return userData.getTeamMap().get(Integer.valueOf(split[1]));
    }

    public List<Long> getBattlefieldUserIdList(int cityId, int partId) {
        String sceneKey = getBattlefieldSceneKey(cityId, partId);
        List<UserScene> sceneUserList = CrossSceneMgr.getSceneUserList(
                config.getActivityInfo().getActivityId(),
                eSceneType.TonBingBattlefield.getValue(),
                sceneKey,
                23333);
        return sceneUserList.stream().mapToLong(UserScene::getUserId).boxed().collect(Collectors.toList());
    }

    /**
     * 领取榜单奖励
     */
    private int getRankReward(long userId, int conditionType) {
        CrossTonBingUserData userData = getUserData(userId);

        // 资格
        if (!isAble(userData)) {
            return GameErrorCode.E_TON_BING_NO_ABLE;
        }

        // 拿职位参数
        CrossTonBingUnionJoin join = unionJoinMap.get(userData.getUnionUid());
        CrossTonBingUnionJoinMember member = join.getMemberMap().get(userId);
        int position = member.getPosition();

        // 拿阵营排名参数
        LinkedList<CrossTonBingRank> campRankList = getCampScoreRankList();
        String myCampId = String.valueOf(userData.getCampId());
        int myCampRank = -1;
        int campRankNum = 0;
        for (CrossTonBingRank rank : campRankList) {
            campRankNum++;
            if (Objects.equals(rank.getId(), myCampId)) {
                myCampRank = campRankNum;
                break;
            }
        }

        // 拿榜单
        String myId;
        LinkedList<CrossTonBingRank> rankList;
        if (conditionType == eGamePlayerEventType.TonBingUserZhanGongRank.getValue()) {
            rankList = userRank.getRankList();
            myId = String.valueOf(userId);
        } else if (conditionType == eGamePlayerEventType.TonBingCampUnionZhanGongRank.getValue()) {
            CrossTonBingRankListModel unionRank = campUnionRankMap.get(userData.getCampId());
            rankList = unionRank == null ? new LinkedList<>() : unionRank.getRankList();
            myId = userData.getUnionUid();
        } else if (conditionType == eGamePlayerEventType.TonBingCampScoreRank.getValue()) {
            rankList = campRankList;
            myId = String.valueOf(userData.getCampId());
        } else {
            return GameErrorCode.E_TON_BING_PARAM_ERR;
        }

        // 【拿榜单排名】
        int myRank = -1;
        int num = 0;
        for (CrossTonBingRank rank : rankList) {
            num++;
            if (Objects.equals(rank.getId(), myId)) {
                myRank = num;
                break;
            }
        }

        TonBingProto.CrossTonBingGetRankRewardRespMsg.Builder builder = TonBingProto.CrossTonBingGetRankRewardRespMsg.newBuilder();
        builder.setRet(0);
        builder.setActivityId(config.getActivityInfo().getActivityId());
        builder.setConditionType(conditionType);
        builder.setPosition(position);
        builder.setRank(myRank);
        builder.setCampRank(myCampRank);
        builder.setUnionId(myId);
        sendPacket(GameProtocol.S_TON_BING_GET_RANK_REWARD_FROM_CROSS, builder, userId);
        return 0;
    }

    /**
     * 阵营积分榜单 变成好多个赛区一起加起来，包括历史的结束的
     */
    public LinkedList<CrossTonBingRank> getCampScoreRankList() {
        Map<Integer, Long> campScoreMap = new ConcurrentHashMap<>();
        Map<Integer, Long> campZhangongMap = new ConcurrentHashMap<>();
        for(CrossTonBingUserData userData : userDataMap.values()){
            long oldValue = campZhangongMap.getOrDefault(userData.getCampId(),0L);
            campZhangongMap.put(userData.getCampId(),oldValue + userData.getZhanGong());
        }
        Map<Integer, Long> updateTimeMap = new ConcurrentHashMap<>();
        LinkedList<CrossTonBingRank> rankList = new LinkedList<>();
        for(CrossTonBingMatch match : matchMap.values()){
            for (CrossTonBingCity city : match.getCrossTonBingData().getCityMap().values()) {
                int campId = city.getCampId();
                int cityId = city.getCityId();

                if (campId == 0) {
                    continue;
                }

                // 统计积分
//                int cityType = config.getCityConfigMap().get(cityId).getType();
//                long addScore = config.getCityTypeConfigMap().get(cityType).getCampPoint();
                long addScore = config.getCityScore(match.getCrossTonBingData().getWarType(),cityId,match.getCrossTonBingData().getTurn());
                long oldScore = campScoreMap.getOrDefault(campId, 0L);
                campScoreMap.put(campId, oldScore + addScore);
                // 存一下时间
                if (city.getOccupyTime() > updateTimeMap.getOrDefault(campId, 0L)) {
                    updateTimeMap.put(campId, city.getOccupyTime());
                }
            }
        }
        for (Map.Entry<Integer, Long> entry : campScoreMap.entrySet()) {
            int campId = entry.getKey();
            String id = String.valueOf(campId);
            CrossTonBingRank rank = new CrossTonBingRank(id, entry.getValue(), updateTimeMap.getOrDefault(entry.getKey(), System.currentTimeMillis()));
            rank.setZhangong(campZhangongMap.getOrDefault(campId,0L));
            rankList.add(rank);
        }
        CrossTonBingRankListModel model = new CrossTonBingRankListModel();
        model.setRankCampList(rankList);
        return model.getRankList();
    }

    /**
     * 通知游戏服condition更新值
     */
    private void notifyConditionChange(long userId, eGamePlayerEventType type, long value) {
        if (type != eGamePlayerEventType.TonBingZhanGong) {
            return;
        }

        TonBingProto.CrossTonBingNotifyConditionRespMsg.Builder builder = TonBingProto.CrossTonBingNotifyConditionRespMsg.newBuilder();
        builder.setUserId(userId);
        builder.setConditionType(type.getValue());
        builder.setValue(value);
        sendPacket(GameProtocol.S_TON_BING_NOTIFY_CONDITION_FROM_CROSS, builder, userId);
    }

    public CrossTonBingRankListModel getUserRank() {
        return userRank;
    }

    public Map<Integer, CrossTonBingRankListModel> getCampUnionRankMap() {
        return campUnionRankMap;
    }

    public Map<String, CrossTonBingUnionJoin> getUnionJoinMap() {
        return unionJoinMap;
    }

    public void changeHorse(long userId, int horseId) {
        CrossTonBingMatch match = getMatchByUserId(userId);
        if(match != null){
            match.changeHorse(userId,horseId);
        }
    }

    /**
     * 邮件补发辎重
     */
    public void mailSendCityCollect() {
        for(CrossTonBingMatch match : matchMap.values()){
            if(!match.isGameOver()){
                match.mailSendCityCollect();
            }
        }
    }

    /**
     * 获取阵营最高战功的玩家
     */
    private UserBaseInfo getCampMaxZhanGongUserBaseInfo(int campId) {
        long userId = getCampMaxZhanGongUserId(campId);
        return userId == 0 ? null : CrossUserMgr.getUserBaseInfo(userId);
    }

    /**
     * 获取阵营最高战功的玩家Id
     */
    private long getCampMaxZhanGongUserId(int campId) {
        long userId = 0;
        CrossTonBingRankListModel rankListModel = campUserRankMap.get(campId);
        if (rankListModel != null) {
            LinkedList<CrossTonBingRank> rankList = rankListModel.getRankList();
            if (!rankList.isEmpty()) {
                CrossTonBingRank first = rankList.getFirst();
                userId = Long.parseLong(first.getId());
            }
        }
        return userId;
    }

    private long getMaxZhanGongUserId() {
        long userId = 0;
        CrossTonBingRank first = userRank.getRankList().getFirst();
        if(first != null){
            userId = Long.parseLong(first.getId());
        }
        return userId;
    }

    // ========= 预留方法 =========

    public void reloadConfig() {
        loadConfigFromDb(config.getActivityInfo());
    }

    public String hotCode(String param) {
        return "";
    }

}
